data grid - handle edge cases (error, structure not loaded)

This commit is contained in:
Jan Prochazka
2021-03-25 08:46:04 +01:00
parent 0d0bd29812
commit 6b0e1e322a
2 changed files with 131 additions and 116 deletions

View File

@@ -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 {

View File

@@ -114,6 +114,7 @@
bind:this={domGrid} bind:this={domGrid}
{...$$props} {...$$props}
onLoadNextData={handleLoadNextData} onLoadNextData={handleLoadNextData}
{errorMessage}
{grider} {grider}
{isLoading} {isLoading}
{allRowCount} {allRowCount}