mirror of
https://github.com/dbgate/dbgate
synced 2024-11-07 20:26:23 +00:00
datagrid
This commit is contained in:
parent
390447c948
commit
fc333167ac
@ -3,11 +3,21 @@
|
||||
--theme-font-2: #4d4d4d;
|
||||
--theme-font-3: #808080;
|
||||
--theme-font-4: #b3b3b3;
|
||||
--theme-font-hover: #061178; /* blue-9 */
|
||||
--theme-font-link: #10239e; /* blue-8 */
|
||||
--theme-font-alt: #135200; /* green-9 */
|
||||
|
||||
--theme-bg-0: #fff;
|
||||
--theme-bg-1: #ededed;
|
||||
--theme-bg-2: #d4d4d4;
|
||||
--theme-bg-3: #bbbbbb;
|
||||
--theme-bg-4: #a2a2a2;
|
||||
--theme-bg-alt: #f0f5ff;
|
||||
|
||||
--theme-bg-gold: #fff1b8; /* gold-2 */
|
||||
--theme-bg-orange: #ffe7ba; /*orange-2 */
|
||||
--theme-bg-green: #d9f7be; /* green-2 */
|
||||
--theme-bg-volcano: #ffd8bf; /* volcano-2 */
|
||||
|
||||
--theme-font-inv-1: #FFFFFF;
|
||||
--theme-font-inv-2: #b3b3b3;
|
||||
@ -22,13 +32,14 @@
|
||||
--theme-border: #ccc;
|
||||
|
||||
--theme-bg-hover: #bae7ff;
|
||||
--theme-bg-selected: #91d5ff; /* blue-3 */
|
||||
|
||||
--theme-bg-statusbar-inv: blue;
|
||||
|
||||
--theme-icon-blue: #096dd9;
|
||||
--theme-icon-green: #237804;
|
||||
--theme-icon-red: #cf1322;
|
||||
--theme-icon-gold: #d48806;
|
||||
--theme-icon-yellow: #d4b106;
|
||||
--theme-icon-magenta: #c41d7f;
|
||||
--theme-icon-blue: #096dd9; /* blue-7 */
|
||||
--theme-icon-green: #237804; /* green-7 */
|
||||
--theme-icon-red: #cf1322; /* red-7 */
|
||||
--theme-icon-gold: #d48806; /* gold-7 */
|
||||
--theme-icon-yellow: #d4b106; /* yellow-7 */
|
||||
--theme-icon-magenta: #c41d7f; /* magenta-7 */
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
z-index: 1;
|
||||
}
|
||||
.grouping {
|
||||
color: green;
|
||||
color: var(--theme-font-alt);
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
127
packages/web/src/datagrid/DataGridCell.svelte
Normal file
127
packages/web/src/datagrid/DataGridCell.svelte
Normal file
@ -0,0 +1,127 @@
|
||||
<script context="module">
|
||||
function makeBulletString(value) {
|
||||
return _.pad('', value.length, '•');
|
||||
}
|
||||
|
||||
function highlightSpecialCharacters(value) {
|
||||
value = value.replace(/\n/g, '↲');
|
||||
value = value.replace(/\r/g, '');
|
||||
value = value.replace(/^(\s+)/, makeBulletString);
|
||||
value = value.replace(/(\s+)$/, makeBulletString);
|
||||
value = value.replace(/(\s\s+)/g, makeBulletString);
|
||||
return value;
|
||||
}
|
||||
|
||||
const dateTimeRegex = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d\d\d)?Z?$/;
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
import { isTypeLogical } from 'dbgate-tools';
|
||||
|
||||
export let rowIndex;
|
||||
export let col;
|
||||
export let rowData;
|
||||
export let hintFieldsAllowed = undefined;
|
||||
|
||||
export let isSelected = false;
|
||||
export let isFrameSelected = false;
|
||||
export let isModifiedRow = false;
|
||||
export let isModifiedCell = false;
|
||||
export let isInserted = false;
|
||||
export let isDeleted = false;
|
||||
|
||||
$: value = rowData[col.uniqueName];
|
||||
</script>
|
||||
|
||||
<td
|
||||
data-row={rowIndex}
|
||||
data-col={col.colIndex}
|
||||
class:isSelected
|
||||
class:isFrameSelected
|
||||
class:isModifiedRow
|
||||
class:isModifiedCell
|
||||
class:isInserted
|
||||
class:isDeleted
|
||||
>
|
||||
{#if value == null}
|
||||
<span class="null">(NULL)</span>
|
||||
{:else if _.isDate(value)}
|
||||
{moment(value).format('YYYY-MM-DD HH:mm:ss')}
|
||||
{:else if value === true}
|
||||
1
|
||||
{:else if value === false}
|
||||
0
|
||||
{:else if _.isNumber(value)}
|
||||
{#if value >= 10000 || value <= -10000}
|
||||
{value.toLocaleString()}
|
||||
{:else}
|
||||
{value.toString()}
|
||||
{/if}
|
||||
{:else if _.isString(value)}
|
||||
{#if dateTimeRegex.test(value)}
|
||||
{moment(value).format('YYYY-MM-DD HH:mm:ss')}
|
||||
{:else}
|
||||
{highlightSpecialCharacters(value)}
|
||||
{/if}
|
||||
{:else if _.isPlainObject(value)}
|
||||
{#if _.isArray(value.data)}
|
||||
{#if value.data.length == 1 && isTypeLogical(col.dataType)}
|
||||
{value.data[0]}
|
||||
{:else}
|
||||
<span class="null">({value.data.length} bytes)</span>
|
||||
{/if}
|
||||
{:else}
|
||||
<span class="null">(RAW)</span>
|
||||
{/if}
|
||||
{:else}
|
||||
{value.toString()}
|
||||
{/if}
|
||||
|
||||
{#if hintFieldsAllowed && hintFieldsAllowed.includes(col.uniqueName)}
|
||||
<span class="hint">{rowData[col.hintColumnName]}</span>
|
||||
{/if}
|
||||
</td>
|
||||
|
||||
<style>
|
||||
td {
|
||||
font-weight: normal;
|
||||
border: 1px solid var(--theme-border);
|
||||
padding: 2px;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
td.isSelected {
|
||||
background: var(--theme-bg-selected);
|
||||
}
|
||||
td.isFrameSelected {
|
||||
outline: 3px solid var(--theme-bg-selected);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
td.isModifiedRow {
|
||||
background: var(--theme-bg-gold);
|
||||
}
|
||||
td.isModifiedCell {
|
||||
background: var(--theme-bg-orange);
|
||||
}
|
||||
td.isInserted {
|
||||
background: var(--theme-bg-green);
|
||||
}
|
||||
td.isDeleted {
|
||||
background: var(--theme-bg-volcano);
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAEElEQVQImWNgIAX8x4KJBAD+agT8INXz9wAAAABJRU5ErkJggg==');
|
||||
background-repeat: repeat-x;
|
||||
background-position: 50% 50%;
|
||||
}
|
||||
|
||||
.hint {
|
||||
color: var(--theme-font-3);
|
||||
margin-left: 5px;
|
||||
}
|
||||
.null {
|
||||
color: var(--theme-font-3);
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
@ -2,6 +2,7 @@
|
||||
import { GridDisplay } from 'dbgate-datalib';
|
||||
import _ from 'lodash';
|
||||
import ColumnHeaderControl from './ColumnHeaderControl.svelte';
|
||||
import DataGridRow from './DataGridRow.svelte';
|
||||
import { countColumnSizes, countVisibleRealColumns } from './gridutil';
|
||||
|
||||
export let loadNextData = undefined;
|
||||
@ -55,13 +56,22 @@
|
||||
<tr>
|
||||
<td class="header-cell" data-row="header" data-col="header" />
|
||||
{#each visibleRealColumns as col (col.uniqueName)}
|
||||
<td class="header-cell" data-row="header" data-col={col.colIndex}>
|
||||
<td
|
||||
class="header-cell"
|
||||
data-row="header"
|
||||
data-col={col.colIndex}
|
||||
style={`width:${col.widthPx}; min-width:${col.widthPx}; max-width:${col.widthPx}`}
|
||||
>
|
||||
<ColumnHeaderControl column={col} {conid} {database} />
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody />
|
||||
<tbody>
|
||||
{#each _.range(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound) as rowIndex (rowIndex)}
|
||||
<DataGridRow {rowIndex} {grider} {visibleRealColumns} />
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@ -84,11 +94,11 @@
|
||||
outline: none;
|
||||
}
|
||||
.header-cell {
|
||||
border: 1px solid var(---theme-border);
|
||||
border: 1px solid var(--theme-border);
|
||||
text-align: left;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: var(---theme-bg-1);
|
||||
background-color: var(--theme-bg-2);
|
||||
overflow: hidden;
|
||||
}
|
||||
.filter-cell {
|
||||
@ -104,7 +114,7 @@
|
||||
}
|
||||
.row-count-label {
|
||||
position: absolute;
|
||||
background-color: var(---theme-bg-2);
|
||||
background-color: var(--theme-bg-2);
|
||||
right: 40px;
|
||||
bottom: 20px;
|
||||
}
|
||||
|
40
packages/web/src/datagrid/DataGridRow.svelte
Normal file
40
packages/web/src/datagrid/DataGridRow.svelte
Normal file
@ -0,0 +1,40 @@
|
||||
<script lang="ts">
|
||||
import DataGridCell from './DataGridCell.svelte';
|
||||
|
||||
import RowHeaderCell from './RowHeaderCell.svelte';
|
||||
|
||||
export let rowHeight;
|
||||
export let rowIndex;
|
||||
export let visibleRealColumns: any[];
|
||||
export let grider;
|
||||
|
||||
$: rowData = grider.getRowData(rowIndex);
|
||||
$: rowStatus = grider.getRowStatus(rowIndex);
|
||||
|
||||
$: hintFieldsAllowed = visibleRealColumns
|
||||
.filter(col => {
|
||||
if (!col.hintColumnName) return false;
|
||||
if (rowStatus.modifiedFields && rowStatus.modifiedFields.has(col.uniqueName)) return false;
|
||||
return true;
|
||||
})
|
||||
.map(col => col.uniqueName);
|
||||
</script>
|
||||
|
||||
<tr>
|
||||
<RowHeaderCell {rowIndex} />
|
||||
{#each visibleRealColumns as col (col.uniqueName)}
|
||||
<DataGridCell {rowIndex} {rowData} {col} {hintFieldsAllowed} />
|
||||
{/each}
|
||||
</tr>
|
||||
|
||||
<style>
|
||||
tr {
|
||||
background-color: var(--theme-bg-0);
|
||||
}
|
||||
tr:nth-child(6n + 3) {
|
||||
background-color: var(--theme-bg-1);
|
||||
}
|
||||
tr:nth-child(6n + 6) {
|
||||
background-color: var(--theme-bg-alt);
|
||||
}
|
||||
</style>
|
18
packages/web/src/datagrid/RowHeaderCell.svelte
Normal file
18
packages/web/src/datagrid/RowHeaderCell.svelte
Normal file
@ -0,0 +1,18 @@
|
||||
<script lang="ts">
|
||||
export let rowIndex;
|
||||
</script>
|
||||
|
||||
<td data-row={rowIndex} data-col="header">
|
||||
{rowIndex + 1}
|
||||
</td>
|
||||
|
||||
<style>
|
||||
td {
|
||||
border: 1px solid var(--theme-border);
|
||||
text-align: left;
|
||||
padding: 2px;
|
||||
background-color: var(--theme-bg-1);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user