mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 14:33:59 +00:00
data grid - handle edge cases (error, structure not loaded)
This commit is contained in:
@@ -243,6 +243,7 @@
|
|||||||
import { clearLastFocusedFormView } from '../formview/FormView.svelte';
|
import { clearLastFocusedFormView } from '../formview/FormView.svelte';
|
||||||
import openReferenceForm, { openPrimaryKeyForm } from '../formview/openReferenceForm';
|
import openReferenceForm, { openPrimaryKeyForm } from '../formview/openReferenceForm';
|
||||||
import openNewTab from '../utility/openNewTab';
|
import openNewTab from '../utility/openNewTab';
|
||||||
|
import ErrorInfo from '../elements/ErrorInfo.svelte';
|
||||||
|
|
||||||
export let onLoadNextData = undefined;
|
export let onLoadNextData = undefined;
|
||||||
export let grider = undefined;
|
export let grider = undefined;
|
||||||
@@ -261,6 +262,7 @@
|
|||||||
export let onOpenQuery = null;
|
export let onOpenQuery = null;
|
||||||
export let onOpenActiveChart = null;
|
export let onOpenActiveChart = null;
|
||||||
export let formViewAvailable = false;
|
export let formViewAvailable = false;
|
||||||
|
export let errorMessage = undefined;
|
||||||
|
|
||||||
export let isLoadedAll;
|
export let isLoadedAll;
|
||||||
export let loadedTime;
|
export let loadedTime;
|
||||||
@@ -1002,142 +1004,154 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
{#if !columns || columns.length == 0}
|
||||||
class="container"
|
<LoadingInfo wrapper message="Waiting for structure" />
|
||||||
bind:clientWidth={containerWidth}
|
{:else if errorMessage}
|
||||||
bind:clientHeight={containerHeight}
|
<ErrorInfo message={errorMessage} />
|
||||||
use:contextMenu={createMenu}
|
{:else if grider.errors && grider.errors.length > 0}
|
||||||
>
|
<div>
|
||||||
<input
|
{#each grider.errors as err}
|
||||||
type="text"
|
<ErrorInfo message={err} key={index} isSmall />
|
||||||
class="focus-field"
|
{/each}
|
||||||
bind:this={domFocusField}
|
</div>
|
||||||
on:keydown={handleGridKeyDown}
|
{:else}
|
||||||
on:focus={() => {
|
<div
|
||||||
lastFocusedDataGrid = instance;
|
class="container"
|
||||||
clearLastFocusedFormView();
|
bind:clientWidth={containerWidth}
|
||||||
invalidateCommands();
|
bind:clientHeight={containerHeight}
|
||||||
}}
|
use:contextMenu={createMenu}
|
||||||
on:paste={handlePaste}
|
|
||||||
/>
|
|
||||||
<table
|
|
||||||
class="table"
|
|
||||||
on:mousedown={handleGridMouseDown}
|
|
||||||
on:mousemove={handleGridMouseMove}
|
|
||||||
on:mouseup={handleGridMouseUp}
|
|
||||||
on:wheel={handleGridWheel}
|
|
||||||
>
|
>
|
||||||
<thead>
|
<input
|
||||||
<tr>
|
type="text"
|
||||||
<td
|
class="focus-field"
|
||||||
class="header-cell"
|
bind:this={domFocusField}
|
||||||
data-row="header"
|
on:keydown={handleGridKeyDown}
|
||||||
data-col="header"
|
on:focus={() => {
|
||||||
bind:clientHeight={rowHeight}
|
lastFocusedDataGrid = instance;
|
||||||
style={`width:${headerColWidth}px; min-width:${headerColWidth}px; max-width:${headerColWidth}px`}
|
clearLastFocusedFormView();
|
||||||
/>
|
invalidateCommands();
|
||||||
{#each visibleRealColumns as col (col.uniqueName)}
|
}}
|
||||||
<td
|
on:paste={handlePaste}
|
||||||
class="header-cell"
|
/>
|
||||||
data-row="header"
|
<table
|
||||||
data-col={col.colIndex}
|
class="table"
|
||||||
style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`}
|
on:mousedown={handleGridMouseDown}
|
||||||
>
|
on:mousemove={handleGridMouseMove}
|
||||||
<ColumnHeaderControl
|
on:mouseup={handleGridMouseUp}
|
||||||
column={col}
|
on:wheel={handleGridWheel}
|
||||||
{conid}
|
>
|
||||||
{database}
|
<thead>
|
||||||
setSort={display.sortable ? order => display.setSort(col.uniqueName, order) : null}
|
|
||||||
order={display.getSortOrder(col.uniqueName)}
|
|
||||||
on:resizeSplitter={e => {
|
|
||||||
// @ts-ignore
|
|
||||||
display.resizeColumn(col.uniqueName, col.width, e.detail);
|
|
||||||
}}
|
|
||||||
setGrouping={display.sortable ? groupFunc => display.setGrouping(col.uniqueName, groupFunc) : null}
|
|
||||||
grouping={display.getGrouping(col.uniqueName)}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
{/each}
|
|
||||||
</tr>
|
|
||||||
{#if display.filterable}
|
|
||||||
<tr>
|
<tr>
|
||||||
<td
|
<td
|
||||||
class="header-cell"
|
class="header-cell"
|
||||||
data-row="filter"
|
data-row="header"
|
||||||
data-col="header"
|
data-col="header"
|
||||||
|
bind:clientHeight={rowHeight}
|
||||||
style={`width:${headerColWidth}px; min-width:${headerColWidth}px; max-width:${headerColWidth}px`}
|
style={`width:${headerColWidth}px; min-width:${headerColWidth}px; max-width:${headerColWidth}px`}
|
||||||
>
|
/>
|
||||||
{#if display.filterCount > 0}
|
|
||||||
<InlineButton on:click={() => display.clearFilters()} square>
|
|
||||||
<FontIcon icon="icon filter-off" />
|
|
||||||
</InlineButton>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{#each visibleRealColumns as col (col.uniqueName)}
|
{#each visibleRealColumns as col (col.uniqueName)}
|
||||||
<td
|
<td
|
||||||
class="filter-cell"
|
class="header-cell"
|
||||||
data-row="filter"
|
data-row="header"
|
||||||
data-col={col.colIndex}
|
data-col={col.colIndex}
|
||||||
style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`}
|
style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`}
|
||||||
>
|
>
|
||||||
<DataFilterControl
|
<ColumnHeaderControl
|
||||||
filterType={getFilterType(col.dataType)}
|
column={col}
|
||||||
filter={display.getFilter(col.uniqueName)}
|
{conid}
|
||||||
setFilter={value => display.setFilter(col.uniqueName, value)}
|
{database}
|
||||||
showResizeSplitter
|
setSort={display.sortable ? order => display.setSort(col.uniqueName, order) : null}
|
||||||
|
order={display.getSortOrder(col.uniqueName)}
|
||||||
on:resizeSplitter={e => {
|
on:resizeSplitter={e => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
display.resizeColumn(col.uniqueName, col.width, e.detail);
|
display.resizeColumn(col.uniqueName, col.width, e.detail);
|
||||||
}}
|
}}
|
||||||
|
setGrouping={display.sortable ? groupFunc => display.setGrouping(col.uniqueName, groupFunc) : null}
|
||||||
|
grouping={display.getGrouping(col.uniqueName)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
{#if display.filterable}
|
||||||
</thead>
|
<tr>
|
||||||
<tbody>
|
<td
|
||||||
{#each _.range(firstVisibleRowScrollIndex, Math.min(firstVisibleRowScrollIndex + visibleRowCountUpperBound, grider.rowCount)) as rowIndex (rowIndex)}
|
class="header-cell"
|
||||||
<DataGridRow
|
data-row="filter"
|
||||||
{rowIndex}
|
data-col="header"
|
||||||
{grider}
|
style={`width:${headerColWidth}px; min-width:${headerColWidth}px; max-width:${headerColWidth}px`}
|
||||||
{visibleRealColumns}
|
>
|
||||||
{rowHeight}
|
{#if display.filterCount > 0}
|
||||||
{autofillSelectedCells}
|
<InlineButton on:click={() => display.clearFilters()} square>
|
||||||
selectedCells={filterCellsForRow(selectedCells, rowIndex)}
|
<FontIcon icon="icon filter-off" />
|
||||||
autofillMarkerCell={filterCellForRow(autofillMarkerCell, rowIndex)}
|
</InlineButton>
|
||||||
focusedColumn={display.focusedColumn}
|
{/if}
|
||||||
inplaceEditorState={$inplaceEditorState}
|
</td>
|
||||||
{dispatchInsplaceEditor}
|
{#each visibleRealColumns as col (col.uniqueName)}
|
||||||
{frameSelection}
|
<td
|
||||||
onSetFormView={formViewAvailable && display?.baseTable?.primaryKey ? handleSetFormView : null}
|
class="filter-cell"
|
||||||
/>
|
data-row="filter"
|
||||||
{/each}
|
data-col={col.colIndex}
|
||||||
</tbody>
|
style={`width:${col.width}px; min-width:${col.width}px; max-width:${col.width}px`}
|
||||||
</table>
|
>
|
||||||
<HorizontalScrollBar
|
<DataFilterControl
|
||||||
minimum={0}
|
filterType={getFilterType(col.dataType)}
|
||||||
maximum={maxScrollColumn}
|
filter={display.getFilter(col.uniqueName)}
|
||||||
viewportRatio={gridScrollAreaWidth / columnSizes.getVisibleScrollSizeSum()}
|
setFilter={value => display.setFilter(col.uniqueName, value)}
|
||||||
on:scroll={e => (firstVisibleColumnScrollIndex = e.detail)}
|
showResizeSplitter
|
||||||
bind:this={domHorizontalScroll}
|
on:resizeSplitter={e => {
|
||||||
/>
|
// @ts-ignore
|
||||||
<VerticalScrollBar
|
display.resizeColumn(col.uniqueName, col.width, e.detail);
|
||||||
minimum={0}
|
}}
|
||||||
maximum={grider.rowCount - visibleRowCountUpperBound + 2}
|
/>
|
||||||
viewportRatio={visibleRowCountUpperBound / grider.rowCount}
|
</td>
|
||||||
on:scroll={e => (firstVisibleRowScrollIndex = e.detail)}
|
{/each}
|
||||||
bind:this={domVerticalScroll}
|
</tr>
|
||||||
/>
|
{/if}
|
||||||
{#if allRowCount}
|
</thead>
|
||||||
<div class="row-count-label">
|
<tbody>
|
||||||
{getRowCountInfo(selectedCells, grider, realColumnUniqueNames, getSelectedRowData(), allRowCount)}
|
{#each _.range(firstVisibleRowScrollIndex, Math.min(firstVisibleRowScrollIndex + visibleRowCountUpperBound, grider.rowCount)) as rowIndex (rowIndex)}
|
||||||
</div>
|
<DataGridRow
|
||||||
{/if}
|
{rowIndex}
|
||||||
|
{grider}
|
||||||
|
{visibleRealColumns}
|
||||||
|
{rowHeight}
|
||||||
|
{autofillSelectedCells}
|
||||||
|
selectedCells={filterCellsForRow(selectedCells, rowIndex)}
|
||||||
|
autofillMarkerCell={filterCellForRow(autofillMarkerCell, rowIndex)}
|
||||||
|
focusedColumn={display.focusedColumn}
|
||||||
|
inplaceEditorState={$inplaceEditorState}
|
||||||
|
{dispatchInsplaceEditor}
|
||||||
|
{frameSelection}
|
||||||
|
onSetFormView={formViewAvailable && display?.baseTable?.primaryKey ? handleSetFormView : null}
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<HorizontalScrollBar
|
||||||
|
minimum={0}
|
||||||
|
maximum={maxScrollColumn}
|
||||||
|
viewportRatio={gridScrollAreaWidth / columnSizes.getVisibleScrollSizeSum()}
|
||||||
|
on:scroll={e => (firstVisibleColumnScrollIndex = e.detail)}
|
||||||
|
bind:this={domHorizontalScroll}
|
||||||
|
/>
|
||||||
|
<VerticalScrollBar
|
||||||
|
minimum={0}
|
||||||
|
maximum={grider.rowCount - visibleRowCountUpperBound + 2}
|
||||||
|
viewportRatio={visibleRowCountUpperBound / grider.rowCount}
|
||||||
|
on:scroll={e => (firstVisibleRowScrollIndex = e.detail)}
|
||||||
|
bind:this={domVerticalScroll}
|
||||||
|
/>
|
||||||
|
{#if allRowCount}
|
||||||
|
<div class="row-count-label">
|
||||||
|
{getRowCountInfo(selectedCells, grider, realColumnUniqueNames, getSelectedRowData(), allRowCount)}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if isLoading}
|
{#if isLoading}
|
||||||
<LoadingInfo wrapper message="Loading data" />
|
<LoadingInfo wrapper message="Loading data" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.container {
|
.container {
|
||||||
|
|||||||
@@ -114,6 +114,7 @@
|
|||||||
bind:this={domGrid}
|
bind:this={domGrid}
|
||||||
{...$$props}
|
{...$$props}
|
||||||
onLoadNextData={handleLoadNextData}
|
onLoadNextData={handleLoadNextData}
|
||||||
|
{errorMessage}
|
||||||
{grider}
|
{grider}
|
||||||
{isLoading}
|
{isLoading}
|
||||||
{allRowCount}
|
{allRowCount}
|
||||||
|
|||||||
Reference in New Issue
Block a user