mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-05-03 11:43:57 +00:00
datagrid
This commit is contained in:
@@ -3,11 +3,21 @@
|
|||||||
--theme-font-2: #4d4d4d;
|
--theme-font-2: #4d4d4d;
|
||||||
--theme-font-3: #808080;
|
--theme-font-3: #808080;
|
||||||
--theme-font-4: #b3b3b3;
|
--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-1: #ededed;
|
||||||
--theme-bg-2: #d4d4d4;
|
--theme-bg-2: #d4d4d4;
|
||||||
--theme-bg-3: #bbbbbb;
|
--theme-bg-3: #bbbbbb;
|
||||||
--theme-bg-4: #a2a2a2;
|
--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-1: #FFFFFF;
|
||||||
--theme-font-inv-2: #b3b3b3;
|
--theme-font-inv-2: #b3b3b3;
|
||||||
@@ -22,13 +32,14 @@
|
|||||||
--theme-border: #ccc;
|
--theme-border: #ccc;
|
||||||
|
|
||||||
--theme-bg-hover: #bae7ff;
|
--theme-bg-hover: #bae7ff;
|
||||||
|
--theme-bg-selected: #91d5ff; /* blue-3 */
|
||||||
|
|
||||||
--theme-bg-statusbar-inv: blue;
|
--theme-bg-statusbar-inv: blue;
|
||||||
|
|
||||||
--theme-icon-blue: #096dd9;
|
--theme-icon-blue: #096dd9; /* blue-7 */
|
||||||
--theme-icon-green: #237804;
|
--theme-icon-green: #237804; /* green-7 */
|
||||||
--theme-icon-red: #cf1322;
|
--theme-icon-red: #cf1322; /* red-7 */
|
||||||
--theme-icon-gold: #d48806;
|
--theme-icon-gold: #d48806; /* gold-7 */
|
||||||
--theme-icon-yellow: #d4b106;
|
--theme-icon-yellow: #d4b106; /* yellow-7 */
|
||||||
--theme-icon-magenta: #c41d7f;
|
--theme-icon-magenta: #c41d7f; /* magenta-7 */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.grouping {
|
.grouping {
|
||||||
color: green;
|
color: var(--theme-font-alt);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</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 { GridDisplay } from 'dbgate-datalib';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import ColumnHeaderControl from './ColumnHeaderControl.svelte';
|
import ColumnHeaderControl from './ColumnHeaderControl.svelte';
|
||||||
|
import DataGridRow from './DataGridRow.svelte';
|
||||||
import { countColumnSizes, countVisibleRealColumns } from './gridutil';
|
import { countColumnSizes, countVisibleRealColumns } from './gridutil';
|
||||||
|
|
||||||
export let loadNextData = undefined;
|
export let loadNextData = undefined;
|
||||||
@@ -55,13 +56,22 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="header-cell" data-row="header" data-col="header" />
|
<td class="header-cell" data-row="header" data-col="header" />
|
||||||
{#each visibleRealColumns as col (col.uniqueName)}
|
{#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} />
|
<ColumnHeaderControl column={col} {conid} {database} />
|
||||||
</td>
|
</td>
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody />
|
<tbody>
|
||||||
|
{#each _.range(firstVisibleRowScrollIndex, firstVisibleRowScrollIndex + visibleRowCountUpperBound) as rowIndex (rowIndex)}
|
||||||
|
<DataGridRow {rowIndex} {grider} {visibleRealColumns} />
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -84,11 +94,11 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
.header-cell {
|
.header-cell {
|
||||||
border: 1px solid var(---theme-border);
|
border: 1px solid var(--theme-border);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: var(---theme-bg-1);
|
background-color: var(--theme-bg-2);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.filter-cell {
|
.filter-cell {
|
||||||
@@ -104,7 +114,7 @@
|
|||||||
}
|
}
|
||||||
.row-count-label {
|
.row-count-label {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: var(---theme-bg-2);
|
background-color: var(--theme-bg-2);
|
||||||
right: 40px;
|
right: 40px;
|
||||||
bottom: 20px;
|
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>
|
||||||
Reference in New Issue
Block a user