support image change and highlight row
This commit is contained in:
parent
171b596ac7
commit
83228a3422
|
@ -5,7 +5,7 @@
|
||||||
:style="{ maxWidth: cellWidth, minWidth: cellWidth }"
|
:style="{ maxWidth: cellWidth, minWidth: cellWidth }"
|
||||||
:tabindex="-1"
|
:tabindex="-1"
|
||||||
@keydown="onCellKeyDown"
|
@keydown="onCellKeyDown"
|
||||||
@dblclick="onCellDoubleClick"
|
@dblclick.prevent="onCellDoubleClick"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:class="[
|
:class="[
|
||||||
|
@ -69,11 +69,11 @@ const emit = defineEmits<{
|
||||||
}>();
|
}>();
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
cell: GridCell,
|
cell: GridCell,
|
||||||
gridSetting: GridRowSetting,
|
rowSetting: GridRowSetting,
|
||||||
bus: GridEventEmitter,
|
bus: GridEventEmitter,
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { cell, gridSetting, bus } = toRefs(props);
|
const { cell, rowSetting, bus } = toRefs(props);
|
||||||
|
|
||||||
const rootEl = shallowRef<InstanceType<typeof HTMLTableCellElement>>();
|
const rootEl = shallowRef<InstanceType<typeof HTMLTableCellElement>>();
|
||||||
const contentAreaEl = shallowRef<InstanceType<typeof HTMLDivElement>>();
|
const contentAreaEl = shallowRef<InstanceType<typeof HTMLDivElement>>();
|
||||||
|
@ -115,7 +115,7 @@ function onCellDoubleClick(ev: MouseEvent) {
|
||||||
|
|
||||||
function onOutsideMouseDown(ev: MouseEvent) {
|
function onOutsideMouseDown(ev: MouseEvent) {
|
||||||
const isOutside = ev.target instanceof Node && !rootEl.value?.contains(ev.target);
|
const isOutside = ev.target instanceof Node && !rootEl.value?.contains(ev.target);
|
||||||
if (isOutside || !equalCellAddress(cell.value.address, getCellAddress(ev.target as HTMLElement, gridSetting.value))) {
|
if (isOutside || !equalCellAddress(cell.value.address, getCellAddress(ev.target as HTMLElement, rowSetting.value))) {
|
||||||
endEditing(true);
|
endEditing(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ function endEditing(applyValue: boolean) {
|
||||||
emit('operation:endEdit', cell.value);
|
emit('operation:endEdit', cell.value);
|
||||||
unregisterOutsideMouseDown();
|
unregisterOutsideMouseDown();
|
||||||
|
|
||||||
if (applyValue) {
|
if (applyValue && editingValue.value !== cell.value.value) {
|
||||||
emitValueChange(editingValue.value);
|
emitValueChange(editingValue.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,23 @@
|
||||||
:class="[
|
:class="[
|
||||||
$style.row,
|
$style.row,
|
||||||
row.ranged ? $style.ranged : {},
|
row.ranged ? $style.ranged : {},
|
||||||
row.additionalStyle?.className ? row.additionalStyle.className : {},
|
...(row.additionalStyles ?? []).map(it => it.className ?? {}),
|
||||||
]"
|
]"
|
||||||
:style="[
|
:style="[
|
||||||
row.additionalStyle?.style ? row.additionalStyle.style : {},
|
...(row.additionalStyles ?? []).map(it => it.style ?? {}),
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<MkNumberCell
|
<MkNumberCell
|
||||||
v-if="gridSetting.showNumber"
|
v-if="setting.showNumber"
|
||||||
:content="(row.index + 1).toString()"
|
:content="(row.index + 1).toString()"
|
||||||
:row="row"
|
:row="row"
|
||||||
/>
|
/>
|
||||||
<MkDataCell
|
<MkDataCell
|
||||||
v-for="cell in cells"
|
v-for="cell in cells"
|
||||||
:key="cell.address.col"
|
:key="cell.address.col"
|
||||||
|
:vIf="cell.column.setting.type !== 'hidden'"
|
||||||
:cell="cell"
|
:cell="cell"
|
||||||
:gridSetting="gridSetting"
|
:rowSetting="setting"
|
||||||
:bus="bus"
|
:bus="bus"
|
||||||
@operation:beginEdit="(sender) => emit('operation:beginEdit', sender)"
|
@operation:beginEdit="(sender) => emit('operation:beginEdit', sender)"
|
||||||
@operation:endEdit="(sender) => emit('operation:endEdit', sender)"
|
@operation:endEdit="(sender) => emit('operation:endEdit', sender)"
|
||||||
|
@ -44,7 +45,7 @@ const emit = defineEmits<{
|
||||||
defineProps<{
|
defineProps<{
|
||||||
row: GridRow,
|
row: GridRow,
|
||||||
cells: GridCell[],
|
cells: GridCell[],
|
||||||
gridSetting: GridRowSetting,
|
setting: GridRowSetting,
|
||||||
bus: GridEventEmitter,
|
bus: GridEventEmitter,
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<thead>
|
<thead>
|
||||||
<MkHeaderRow
|
<MkHeaderRow
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:gridSetting="gridSetting"
|
:gridSetting="rowSetting"
|
||||||
:bus="bus"
|
:bus="bus"
|
||||||
@operation:beginWidthChange="onHeaderCellWidthBeginChange"
|
@operation:beginWidthChange="onHeaderCellWidthBeginChange"
|
||||||
@operation:endWidthChange="onHeaderCellWidthEndChange"
|
@operation:endWidthChange="onHeaderCellWidthEndChange"
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
:key="row.index"
|
:key="row.index"
|
||||||
:row="row"
|
:row="row"
|
||||||
:cells="cells[row.index].cells"
|
:cells="cells[row.index].cells"
|
||||||
:gridSetting="gridSetting"
|
:setting="rowSetting"
|
||||||
:bus="bus"
|
:bus="bus"
|
||||||
:using="row.using"
|
:using="row.using"
|
||||||
:class="[ lastLine === row.index ? $style.lastLine : {} ]"
|
:class="[ lastLine === row.index ? $style.lastLine : {} ]"
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref, toRefs, watch } from 'vue';
|
import { computed, onMounted, ref, toRefs, watch } from 'vue';
|
||||||
import { DataSource, GridEventEmitter, GridState, Size } from '@/components/grid/grid.js';
|
import { DataSource, GridEventEmitter, GridSetting, GridState, Size } from '@/components/grid/grid.js';
|
||||||
import MkDataRow from '@/components/grid/MkDataRow.vue';
|
import MkDataRow from '@/components/grid/MkDataRow.vue';
|
||||||
import MkHeaderRow from '@/components/grid/MkHeaderRow.vue';
|
import MkHeaderRow from '@/components/grid/MkHeaderRow.vue';
|
||||||
import { cellValidation } from '@/components/grid/cell-validators.js';
|
import { cellValidation } from '@/components/grid/cell-validators.js';
|
||||||
|
@ -49,8 +49,8 @@ import { equalCellAddress, getCellAddress, getCellElement } from '@/components/g
|
||||||
import { MenuItem } from '@/types/menu.js';
|
import { MenuItem } from '@/types/menu.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { GridCurrentState, GridEvent } from '@/components/grid/grid-event.js';
|
import { GridCurrentState, GridEvent } from '@/components/grid/grid-event.js';
|
||||||
import { createColumn, GridColumn, GridColumnSetting } from '@/components/grid/column.js';
|
import { createColumn, GridColumn } from '@/components/grid/column.js';
|
||||||
import { createRow, defaultGridSetting, GridRow, GridRowSetting, resetRow } from '@/components/grid/row.js';
|
import { createRow, defaultGridRowSetting, GridRow, GridRowSetting, resetRow } from '@/components/grid/row.js';
|
||||||
|
|
||||||
type RowHolder = {
|
type RowHolder = {
|
||||||
row: GridRow,
|
row: GridRow,
|
||||||
|
@ -63,19 +63,18 @@ const emit = defineEmits<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
gridSetting?: GridRowSetting,
|
settings: GridSetting,
|
||||||
columnSettings: GridColumnSetting[],
|
|
||||||
data: DataSource[]
|
data: DataSource[]
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// non-reactive
|
// non-reactive
|
||||||
const gridSetting: Required<GridRowSetting> = {
|
const rowSetting: Required<GridRowSetting> = {
|
||||||
...props.gridSetting,
|
...defaultGridRowSetting,
|
||||||
...defaultGridSetting,
|
...props.settings.row,
|
||||||
};
|
};
|
||||||
|
|
||||||
// non-reactive
|
// non-reactive
|
||||||
const columnSettings = props.columnSettings;
|
const columnSettings = props.settings.cols;
|
||||||
|
|
||||||
const { data } = toRefs(props);
|
const { data } = toRefs(props);
|
||||||
|
|
||||||
|
@ -434,7 +433,7 @@ function onMouseDown(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLeftMouseDown(ev: MouseEvent) {
|
function onLeftMouseDown(ev: MouseEvent) {
|
||||||
const cellAddress = getCellAddress(ev.target as HTMLElement, gridSetting);
|
const cellAddress = getCellAddress(ev.target as HTMLElement, rowSetting);
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
console.log(`[grid][mouse-left] state:${state.value}, button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
console.log(`[grid][mouse-left] state:${state.value}, button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
||||||
}
|
}
|
||||||
|
@ -568,7 +567,7 @@ function onLeftMouseDown(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRightMouseDown(ev: MouseEvent) {
|
function onRightMouseDown(ev: MouseEvent) {
|
||||||
const cellAddress = getCellAddress(ev.target as HTMLElement, gridSetting);
|
const cellAddress = getCellAddress(ev.target as HTMLElement, rowSetting);
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
console.log(`[grid][mouse-right] button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
console.log(`[grid][mouse-right] button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
||||||
}
|
}
|
||||||
|
@ -593,7 +592,7 @@ function onRightMouseDown(ev: MouseEvent) {
|
||||||
function onMouseMove(ev: MouseEvent) {
|
function onMouseMove(ev: MouseEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
const targetCellAddress = getCellAddress(ev.target as HTMLElement, gridSetting);
|
const targetCellAddress = getCellAddress(ev.target as HTMLElement, rowSetting);
|
||||||
if (equalCellAddress(previousCellAddress.value, targetCellAddress)) {
|
if (equalCellAddress(previousCellAddress.value, targetCellAddress)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -696,7 +695,7 @@ function onMouseUp(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onContextMenu(ev: MouseEvent) {
|
function onContextMenu(ev: MouseEvent) {
|
||||||
const cellAddress = getCellAddress(ev.target as HTMLElement, gridSetting);
|
const cellAddress = getCellAddress(ev.target as HTMLElement, rowSetting);
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
console.log(`[grid][context-menu] button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
console.log(`[grid][context-menu] button: ${ev.button}, cell: ${cellAddress.row}x${cellAddress.col}`);
|
||||||
}
|
}
|
||||||
|
@ -734,6 +733,7 @@ function onCellEditEnd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onChangeCellValue(sender: GridCell, newValue: CellValue) {
|
function onChangeCellValue(sender: GridCell, newValue: CellValue) {
|
||||||
|
applyRowRules([sender]);
|
||||||
emitCellValue(sender, newValue);
|
emitCellValue(sender, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -972,7 +972,7 @@ function expandCellRange(leftTop: CellAddress, rightBottom: CellAddress) {
|
||||||
* {@link top}から{@link bottom}までの行を範囲選択状態にする。
|
* {@link top}から{@link bottom}までの行を範囲選択状態にする。
|
||||||
*/
|
*/
|
||||||
function expandRowRange(top: number, bottom: number) {
|
function expandRowRange(top: number, bottom: number) {
|
||||||
if (!gridSetting.selectable) {
|
if (!rowSetting.selectable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,6 +982,31 @@ function expandRowRange(top: number, bottom: number) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyRowRules(targetCells: GridCell[]) {
|
||||||
|
const _rows = rows.value;
|
||||||
|
const targetRowIdxes = [...new Set(targetCells.map(it => it.address.row))];
|
||||||
|
const rowGroups = Array.of<{ row: GridRow, cells: GridCell[] }>();
|
||||||
|
for (const rowIdx of targetRowIdxes) {
|
||||||
|
const rowGroup = targetCells.filter(it => it.address.row === rowIdx);
|
||||||
|
rowGroups.push({ row: _rows[rowIdx], cells: rowGroup });
|
||||||
|
}
|
||||||
|
|
||||||
|
const _cells = cells.value;
|
||||||
|
for (const group of rowGroups.filter(it => it.row.using)) {
|
||||||
|
const row = group.row;
|
||||||
|
const targetCols = group.cells.map(it => it.column);
|
||||||
|
const cells = _cells[group.row.index].cells;
|
||||||
|
|
||||||
|
const newStyles = rowSetting.styleRules
|
||||||
|
.filter(it => it.condition({ row, targetCols, cells }))
|
||||||
|
.map(it => it.applyStyle);
|
||||||
|
|
||||||
|
if (JSON.stringify(newStyles) !== JSON.stringify(row.additionalStyles)) {
|
||||||
|
row.additionalStyles = newStyles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function availableCellAddress(cellAddress: CellAddress): boolean {
|
function availableCellAddress(cellAddress: CellAddress): boolean {
|
||||||
return cellAddress.row >= 0 && cellAddress.col >= 0 && cellAddress.row < rows.value.length && cellAddress.col < columns.value.length;
|
return cellAddress.row >= 0 && cellAddress.col >= 0 && cellAddress.row < rows.value.length && cellAddress.col < columns.value.length;
|
||||||
}
|
}
|
||||||
|
@ -1018,9 +1043,9 @@ function refreshData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const _data: DataSource[] = data.value;
|
const _data: DataSource[] = data.value;
|
||||||
const _rows: GridRow[] = (_data.length > gridSetting.minimumDefinitionCount)
|
const _rows: GridRow[] = (_data.length > rowSetting.minimumDefinitionCount)
|
||||||
? _data.map((_, index) => createRow(index, true))
|
? _data.map((_, index) => createRow(index, true))
|
||||||
: Array.from({ length: gridSetting.minimumDefinitionCount }, (_, index) => createRow(index, index < _data.length));
|
: Array.from({ length: rowSetting.minimumDefinitionCount }, (_, index) => createRow(index, index < _data.length));
|
||||||
const _cols: GridColumn[] = columns.value;
|
const _cols: GridColumn[] = columns.value;
|
||||||
|
|
||||||
// 行・列の定義から、元データの配列より値を取得してセルを作成する。
|
// 行・列の定義から、元データの配列より値を取得してセルを作成する。
|
||||||
|
@ -1028,11 +1053,11 @@ function refreshData() {
|
||||||
const _cells: RowHolder[] = _rows.map(row => {
|
const _cells: RowHolder[] = _rows.map(row => {
|
||||||
const cells = row.using
|
const cells = row.using
|
||||||
? _cols.map(col => {
|
? _cols.map(col => {
|
||||||
const cell = createCell(col, row, _data[row.index][col.setting.bindTo], col.setting.cellSetting ?? {});
|
const cell = createCell(col, row, _data[row.index][col.setting.bindTo]);
|
||||||
cell.violation = cellValidation(cell, cell.value);
|
cell.violation = cellValidation(cell, cell.value);
|
||||||
return cell;
|
return cell;
|
||||||
})
|
})
|
||||||
: _cols.map(col => createCell(col, row, undefined, col.setting.cellSetting ?? {}));
|
: _cols.map(col => createCell(col, row, undefined));
|
||||||
|
|
||||||
return { row, cells, origin: _data[row.index] };
|
return { row, cells, origin: _data[row.index] };
|
||||||
});
|
});
|
||||||
|
@ -1040,6 +1065,8 @@ function refreshData() {
|
||||||
rows.value = _rows;
|
rows.value = _rows;
|
||||||
cells.value = _cells;
|
cells.value = _cells;
|
||||||
|
|
||||||
|
applyRowRules(_cells.filter(it => it.row.using).flatMap(it => it.cells));
|
||||||
|
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
console.log('[grid][refresh-data][end]');
|
console.log('[grid][refresh-data][end]');
|
||||||
}
|
}
|
||||||
|
@ -1057,7 +1084,7 @@ function refreshData() {
|
||||||
*/
|
*/
|
||||||
function patchData(newItems: DataSource[]) {
|
function patchData(newItems: DataSource[]) {
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
console.log(`[grid][patch-data][begin] new:${newItems.length} old:${cells.value.length}`);
|
console.log('[grid][patch-data][begin]');
|
||||||
}
|
}
|
||||||
|
|
||||||
const _cols = columns.value;
|
const _cols = columns.value;
|
||||||
|
@ -1079,13 +1106,16 @@ function patchData(newItems: DataSource[]) {
|
||||||
|
|
||||||
rows.value.push(...newRows);
|
rows.value.push(...newRows);
|
||||||
cells.value.push(...newCells);
|
cells.value.push(...newCells);
|
||||||
|
|
||||||
|
applyRowRules(newCells.flatMap(it => it.cells));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 行数の上限が欲しい場合はここに設けてもいいかもしれない
|
// 行数の上限が欲しい場合はここに設けてもいいかもしれない
|
||||||
|
|
||||||
if (rows.value.length > newItems.length) {
|
const usingRows = rows.value.filter(it => it.using);
|
||||||
|
if (usingRows.length > newItems.length) {
|
||||||
// 行数が減っているので古い行をクリアする(再マウント・再レンダリングが重いので要素そのものは消さない)
|
// 行数が減っているので古い行をクリアする(再マウント・再レンダリングが重いので要素そのものは消さない)
|
||||||
for (let rowIdx = newItems.length; rowIdx < rows.value.length; rowIdx++) {
|
for (let rowIdx = newItems.length; rowIdx < usingRows.length; rowIdx++) {
|
||||||
resetRow(rows.value[rowIdx]);
|
resetRow(rows.value[rowIdx]);
|
||||||
for (let colIdx = 0; colIdx < _cols.length; colIdx++) {
|
for (let colIdx = 0; colIdx < _cols.length; colIdx++) {
|
||||||
const holder = cells.value[rowIdx];
|
const holder = cells.value[rowIdx];
|
||||||
|
@ -1095,6 +1125,7 @@ function patchData(newItems: DataSource[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const changedCells = Array.of<GridCell>();
|
||||||
for (let rowIdx = 0; rowIdx < newItems.length; rowIdx++) {
|
for (let rowIdx = 0; rowIdx < newItems.length; rowIdx++) {
|
||||||
const holder = cells.value[rowIdx];
|
const holder = cells.value[rowIdx];
|
||||||
holder.row.using = true;
|
holder.row.using = true;
|
||||||
|
@ -1109,19 +1140,24 @@ function patchData(newItems: DataSource[]) {
|
||||||
if (oldCell.value !== newValue) {
|
if (oldCell.value !== newValue) {
|
||||||
oldCell.violation = cellValidation(oldCell, newValue);
|
oldCell.violation = cellValidation(oldCell, newValue);
|
||||||
oldCell.value = newValue;
|
oldCell.value = newValue;
|
||||||
|
changedCells.push(oldCell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// セル値が書き換わっており、バリデーションの結果も変わっているので外部に通知する必要がある
|
if (changedCells.length > 0) {
|
||||||
emitGridEvent({
|
applyRowRules(changedCells);
|
||||||
type: 'cell-validation',
|
|
||||||
all: cells.value
|
// セル値が書き換わっており、バリデーションの結果も変わっているので外部に通知する必要がある
|
||||||
.filter(it => it.row.using)
|
emitGridEvent({
|
||||||
.flatMap(it => it.cells)
|
type: 'cell-validation',
|
||||||
.map(it => it.violation)
|
all: cells.value
|
||||||
.filter(it => !it.valid),
|
.filter(it => it.row.using)
|
||||||
});
|
.flatMap(it => it.cells)
|
||||||
|
.map(it => it.violation)
|
||||||
|
.filter(it => !it.valid),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (_DEV_) {
|
if (_DEV_) {
|
||||||
console.log('[grid][patch-data][end]');
|
console.log('[grid][patch-data][end]');
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { ValidateViolation } from '@/components/grid/cell-validators.js';
|
import { ValidateViolation } from '@/components/grid/cell-validators.js';
|
||||||
import { AdditionalStyle, EventOptions, Size } from '@/components/grid/grid.js';
|
import { Size } from '@/components/grid/grid.js';
|
||||||
import { GridColumn } from '@/components/grid/column.js';
|
import { GridColumn } from '@/components/grid/column.js';
|
||||||
import { GridRow } from '@/components/grid/row.js';
|
import { GridRow } from '@/components/grid/row.js';
|
||||||
import { MenuItem } from '@/types/menu.js';
|
|
||||||
|
|
||||||
export type CellValue = string | boolean | number | undefined | null
|
export type CellValue = string | boolean | number | undefined | null
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import { CellValidator } from '@/components/grid/cell-validators.js';
|
import { CellValidator } from '@/components/grid/cell-validators.js';
|
||||||
import { AdditionalStyle, EventOptions, Size, SizeStyle } from '@/components/grid/grid.js';
|
import { Size, SizeStyle } from '@/components/grid/grid.js';
|
||||||
import { calcCellWidth } from '@/components/grid/grid-utils.js';
|
import { calcCellWidth } from '@/components/grid/grid-utils.js';
|
||||||
import { CellValue, GridCell, GridCellSetting } from '@/components/grid/cell.js';
|
|
||||||
import { GridRow } from '@/components/grid/row.js';
|
|
||||||
|
|
||||||
export type ColumnType = 'text' | 'number' | 'date' | 'boolean' | 'image';
|
export type ColumnType = 'text' | 'number' | 'date' | 'boolean' | 'image' | 'hidden';
|
||||||
|
|
||||||
export type GridColumnSetting = {
|
export type GridColumnSetting = {
|
||||||
bindTo: string;
|
bindTo: string;
|
||||||
|
@ -14,8 +12,6 @@ export type GridColumnSetting = {
|
||||||
width: SizeStyle;
|
width: SizeStyle;
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
validators?: CellValidator[];
|
validators?: CellValidator[];
|
||||||
valueConverter?: GridColumnValueConverter;
|
|
||||||
cellSetting?: GridCellSetting;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GridColumn = {
|
export type GridColumn = {
|
||||||
|
@ -25,13 +21,6 @@ export type GridColumn = {
|
||||||
contentSize: Size;
|
contentSize: Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GridColumnValueConverter = (row: GridRow, col: GridColumn, value: CellValue) => CellValue;
|
|
||||||
|
|
||||||
export type GridColumnEventArgs = {
|
|
||||||
col: GridColumn;
|
|
||||||
cells: GridCell[];
|
|
||||||
} & EventOptions;
|
|
||||||
|
|
||||||
export function createColumn(setting: GridColumnSetting, index: number): GridColumn {
|
export function createColumn(setting: GridColumnSetting, index: number): GridColumn {
|
||||||
return {
|
return {
|
||||||
index,
|
index,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { GridColumnSetting } from '@/components/grid/column.js';
|
||||||
import { GridRowSetting } from '@/components/grid/row.js';
|
import { GridRowSetting } from '@/components/grid/row.js';
|
||||||
|
|
||||||
export type GridSetting = {
|
export type GridSetting = {
|
||||||
row: GridRowSetting;
|
row?: GridRowSetting;
|
||||||
cols: GridColumnSetting[];
|
cols: GridColumnSetting[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,11 +27,6 @@ export type Size = {
|
||||||
|
|
||||||
export type SizeStyle = number | 'auto' | undefined;
|
export type SizeStyle = number | 'auto' | undefined;
|
||||||
|
|
||||||
export type EventOptions = {
|
|
||||||
preventDefault?: boolean;
|
|
||||||
stopPropagation?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type AdditionalStyle = {
|
export type AdditionalStyle = {
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: Record<string, string | number>;
|
style?: Record<string, string | number>;
|
||||||
|
|
|
@ -1,22 +1,37 @@
|
||||||
import { AdditionalStyle } from '@/components/grid/grid.js';
|
import { AdditionalStyle } from '@/components/grid/grid.js';
|
||||||
|
import { GridCell } from '@/components/grid/cell.js';
|
||||||
|
import { GridColumn } from '@/components/grid/column.js';
|
||||||
|
|
||||||
export const defaultGridSetting: Required<GridRowSetting> = {
|
export const defaultGridRowSetting: Required<GridRowSetting> = {
|
||||||
showNumber: true,
|
showNumber: true,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
minimumDefinitionCount: 100,
|
minimumDefinitionCount: 100,
|
||||||
|
styleRules: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GridRowStyleRuleConditionParams = {
|
||||||
|
row: GridRow,
|
||||||
|
targetCols: GridColumn[],
|
||||||
|
cells: GridCell[]
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GridRowStyleRule = {
|
||||||
|
condition: (params: GridRowStyleRuleConditionParams) => boolean;
|
||||||
|
applyStyle: AdditionalStyle;
|
||||||
|
}
|
||||||
|
|
||||||
export type GridRowSetting = {
|
export type GridRowSetting = {
|
||||||
showNumber?: boolean;
|
showNumber?: boolean;
|
||||||
selectable?: boolean;
|
selectable?: boolean;
|
||||||
minimumDefinitionCount?: number;
|
minimumDefinitionCount?: number;
|
||||||
|
styleRules?: GridRowStyleRule[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GridRow = {
|
export type GridRow = {
|
||||||
index: number;
|
index: number;
|
||||||
ranged: boolean;
|
ranged: boolean;
|
||||||
using: boolean;
|
using: boolean;
|
||||||
additionalStyle?: AdditionalStyle;
|
additionalStyles: AdditionalStyle[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createRow(index: number, using: boolean): GridRow {
|
export function createRow(index: number, using: boolean): GridRow {
|
||||||
|
@ -24,12 +39,13 @@ export function createRow(index: number, using: boolean): GridRow {
|
||||||
index,
|
index,
|
||||||
ranged: false,
|
ranged: false,
|
||||||
using: using,
|
using: using,
|
||||||
|
additionalStyles: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetRow(row: GridRow): void {
|
export function resetRow(row: GridRow): void {
|
||||||
row.ranged = false;
|
row.ranged = false;
|
||||||
row.using = false;
|
row.using = false;
|
||||||
row.additionalStyle = undefined;
|
row.additionalStyles = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<div :class="$style.gridArea">
|
<div :class="$style.gridArea">
|
||||||
<MkGrid :data="gridItems" :gridSetting="gridSetting" :columnSettings="columnSettings" @event="onGridEvent"/>
|
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MkPagingButtons :current="currentPage" :max="allPages" :buttonCount="5" @pageChanged="onPageChanged"/>
|
<MkPagingButtons :current="currentPage" :max="allPages" :buttonCount="5" @pageChanged="onPageChanged"/>
|
||||||
|
@ -113,7 +113,6 @@ import MkGrid from '@/components/grid/MkGrid.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import { GridColumnSetting } from '@/components/grid/column.js';
|
|
||||||
import { validators } from '@/components/grid/cell-validators.js';
|
import { validators } from '@/components/grid/cell-validators.js';
|
||||||
import {
|
import {
|
||||||
GridCellContextMenuEvent,
|
GridCellContextMenuEvent,
|
||||||
|
@ -131,7 +130,7 @@ import XRegisterLogs from '@/pages/admin/custom-emojis-grid.local.logs.vue';
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
import { deviceKind } from '@/scripts/device-kind.js';
|
import { deviceKind } from '@/scripts/device-kind.js';
|
||||||
import { GridRowSetting } from '@/components/grid/row.js';
|
import { GridSetting } from '@/components/grid/grid.js';
|
||||||
|
|
||||||
type GridItem = {
|
type GridItem = {
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
|
@ -146,26 +145,42 @@ type GridItem = {
|
||||||
localOnly: boolean;
|
localOnly: boolean;
|
||||||
roleIdsThatCanBeUsedThisEmojiAsReaction: string;
|
roleIdsThatCanBeUsedThisEmojiAsReaction: string;
|
||||||
fileId?: string;
|
fileId?: string;
|
||||||
|
updatedAt: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gridSetting: GridRowSetting = {
|
function setupGrid(): GridSetting {
|
||||||
showNumber: true,
|
const required = validators.required();
|
||||||
selectable: false,
|
const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
|
||||||
};
|
return {
|
||||||
|
row: {
|
||||||
const required = validators.required();
|
showNumber: true,
|
||||||
const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
|
selectable: true,
|
||||||
const columnSettings: GridColumnSetting[] = [
|
minimumDefinitionCount: 100,
|
||||||
{ bindTo: 'checked', icon: 'ti-trash', type: 'boolean', editable: true, width: 34 },
|
styleRules: [
|
||||||
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto', validators: [required] },
|
{
|
||||||
{ bindTo: 'name', title: 'name', type: 'text', editable: true, width: 140, validators: [required, regex] },
|
condition: ({ row }) => JSON.stringify(gridItems.value[row.index]) !== JSON.stringify(originGridItems.value[row.index]),
|
||||||
{ bindTo: 'category', title: 'category', type: 'text', editable: true, width: 140 },
|
applyStyle: { className: 'changedRow' },
|
||||||
{ bindTo: 'aliases', title: 'aliases', type: 'text', editable: true, width: 140 },
|
},
|
||||||
{ bindTo: 'license', title: 'license', type: 'text', editable: true, width: 140 },
|
{
|
||||||
{ bindTo: 'isSensitive', title: 'sensitive', type: 'boolean', editable: true, width: 90 },
|
condition: ({ cells }) => cells.some(it => !it.violation.valid),
|
||||||
{ bindTo: 'localOnly', title: 'localOnly', type: 'boolean', editable: true, width: 90 },
|
applyStyle: { className: 'violationRow' },
|
||||||
{ bindTo: 'roleIdsThatCanBeUsedThisEmojiAsReaction', title: 'role', type: 'text', editable: true, width: 140 },
|
},
|
||||||
];
|
],
|
||||||
|
},
|
||||||
|
cols: [
|
||||||
|
{ bindTo: 'checked', icon: 'ti-trash', type: 'boolean', editable: true, width: 34 },
|
||||||
|
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: true, width: 'auto', validators: [required] },
|
||||||
|
{ bindTo: 'name', title: 'name', type: 'text', editable: true, width: 140, validators: [required, regex] },
|
||||||
|
{ bindTo: 'category', title: 'category', type: 'text', editable: true, width: 140 },
|
||||||
|
{ bindTo: 'aliases', title: 'aliases', type: 'text', editable: true, width: 140 },
|
||||||
|
{ bindTo: 'license', title: 'license', type: 'text', editable: true, width: 140 },
|
||||||
|
{ bindTo: 'isSensitive', title: 'sensitive', type: 'boolean', editable: true, width: 90 },
|
||||||
|
{ bindTo: 'localOnly', title: 'localOnly', type: 'boolean', editable: true, width: 90 },
|
||||||
|
{ bindTo: 'roleIdsThatCanBeUsedThisEmojiAsReaction', title: 'role', type: 'text', editable: true, width: 140 },
|
||||||
|
{ bindTo: 'updatedAt', type: 'hidden', editable: false, width: 'auto' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const customEmojis = ref<Misskey.entities.EmojiDetailedAdmin[]>([]);
|
const customEmojis = ref<Misskey.entities.EmojiDetailedAdmin[]>([]);
|
||||||
const allPages = ref<number>(0);
|
const allPages = ref<number>(0);
|
||||||
|
@ -229,7 +244,7 @@ async function onUpdateButtonClicked() {
|
||||||
isSensitive: item.isSensitive,
|
isSensitive: item.isSensitive,
|
||||||
localOnly: item.localOnly,
|
localOnly: item.localOnly,
|
||||||
roleIdsThatCanBeUsedThisEmojiAsReaction: emptyStrToEmptyArray(item.roleIdsThatCanBeUsedThisEmojiAsReaction),
|
roleIdsThatCanBeUsedThisEmojiAsReaction: emptyStrToEmptyArray(item.roleIdsThatCanBeUsedThisEmojiAsReaction),
|
||||||
fileId: item.fileId,
|
fileId: item.fileId,
|
||||||
})
|
})
|
||||||
.then(() => ({ item, success: true, err: undefined }))
|
.then(() => ({ item, success: true, err: undefined }))
|
||||||
.catch(err => ({ item, success: false, err })),
|
.catch(err => ({ item, success: false, err })),
|
||||||
|
@ -399,15 +414,6 @@ function onGridCellValueChange(event: GridCellValueChangeEvent) {
|
||||||
} else {
|
} else {
|
||||||
gridItems.value[row.index][column.setting.bindTo] = newValue;
|
gridItems.value[row.index][column.setting.bindTo] = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const originItem = originGridItems.value[row.index][column.setting.bindTo];
|
|
||||||
if (originItem !== newValue) {
|
|
||||||
row.additionalStyle = {
|
|
||||||
className: 'editedRow',
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
row.additionalStyle = undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,14 +452,6 @@ async function onGridKeyDown(event: GridKeyDownEvent, currentState: GridCurrentS
|
||||||
for (const cell of ranges) {
|
for (const cell of ranges) {
|
||||||
if (cell.column.setting.editable) {
|
if (cell.column.setting.editable) {
|
||||||
gridItems.value[cell.row.index][cell.column.setting.bindTo] = undefined;
|
gridItems.value[cell.row.index][cell.column.setting.bindTo] = undefined;
|
||||||
const originItem = originGridItems.value[cell.row.index][cell.column.setting.bindTo];
|
|
||||||
if (originItem !== undefined) {
|
|
||||||
cell.row.additionalStyle = {
|
|
||||||
className: 'editedRow',
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
cell.row.additionalStyle = undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -519,6 +517,7 @@ function refreshGridItems() {
|
||||||
isSensitive: it.isSensitive,
|
isSensitive: it.isSensitive,
|
||||||
localOnly: it.localOnly,
|
localOnly: it.localOnly,
|
||||||
roleIdsThatCanBeUsedThisEmojiAsReaction: it.roleIdsThatCanBeUsedThisEmojiAsReaction.join(', '),
|
roleIdsThatCanBeUsedThisEmojiAsReaction: it.roleIdsThatCanBeUsedThisEmojiAsReaction.join(', '),
|
||||||
|
updatedAt: it.updatedAt,
|
||||||
}));
|
}));
|
||||||
originGridItems.value = JSON.parse(JSON.stringify(gridItems.value));
|
originGridItems.value = JSON.parse(JSON.stringify(gridItems.value));
|
||||||
}
|
}
|
||||||
|
@ -529,6 +528,16 @@ onMounted(async () => {
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.violationRow {
|
||||||
|
background-color: var(--infoWarnBg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.changedRow {
|
||||||
|
background-color: var(--infoBg);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.editedRow {
|
.editedRow {
|
||||||
background-color: var(--infoBg);
|
background-color: var(--infoBg);
|
||||||
|
|
|
@ -7,9 +7,8 @@
|
||||||
<div>
|
<div>
|
||||||
<div v-if="filteredLogs.length > 0">
|
<div v-if="filteredLogs.length > 0">
|
||||||
<MkGrid
|
<MkGrid
|
||||||
:gridSetting="{ rowNumberVisible: false, rowSelectable: false }"
|
|
||||||
:data="filteredLogs"
|
:data="filteredLogs"
|
||||||
:columnSettings="columnSettings"
|
:settings="setupGrid()"
|
||||||
@event="onGridEvent"
|
@event="onGridEvent"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -39,13 +38,22 @@ import {
|
||||||
import { optInGridUtils } from '@/components/grid/optin-utils.js';
|
import { optInGridUtils } from '@/components/grid/optin-utils.js';
|
||||||
import MkGrid from '@/components/grid/MkGrid.vue';
|
import MkGrid from '@/components/grid/MkGrid.vue';
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
|
import { GridSetting } from '@/components/grid/grid.js';
|
||||||
|
|
||||||
const columnSettings: GridColumnSetting[] = [
|
function setupGrid(): GridSetting {
|
||||||
{ bindTo: 'failed', title: 'failed', type: 'boolean', editable: false, width: 50 },
|
return {
|
||||||
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto' },
|
row: {
|
||||||
{ bindTo: 'name', title: 'name', type: 'text', editable: false, width: 140 },
|
showNumber: false,
|
||||||
{ bindTo: 'error', title: 'log', type: 'text', editable: false, width: 'auto' },
|
selectable: false,
|
||||||
];
|
},
|
||||||
|
cols: [
|
||||||
|
{ bindTo: 'failed', title: 'failed', type: 'boolean', editable: false, width: 50 },
|
||||||
|
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto' },
|
||||||
|
{ bindTo: 'name', title: 'name', type: 'text', editable: false, width: 140 },
|
||||||
|
{ bindTo: 'error', title: 'log', type: 'text', editable: false, width: 'auto' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
logs: RequestLogItem[];
|
logs: RequestLogItem[];
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
<div v-if="gridItems.length > 0" :class="$style.gridArea">
|
<div v-if="gridItems.length > 0" :class="$style.gridArea">
|
||||||
<MkGrid
|
<MkGrid
|
||||||
:data="gridItems"
|
:data="gridItems"
|
||||||
:columnSettings="columnSettings"
|
:settings="setupGrid()"
|
||||||
@event="onGridEvent"
|
@event="onGridEvent"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,11 +75,7 @@
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import {
|
import { emptyStrToEmptyArray, emptyStrToNull, RequestLogItem } from '@/pages/admin/custom-emojis-grid.impl.js';
|
||||||
emptyStrToEmptyArray,
|
|
||||||
emptyStrToNull,
|
|
||||||
RequestLogItem,
|
|
||||||
} from '@/pages/admin/custom-emojis-grid.impl.js';
|
|
||||||
import MkGrid from '@/components/grid/MkGrid.vue';
|
import MkGrid from '@/components/grid/MkGrid.vue';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
|
@ -100,10 +96,10 @@ import {
|
||||||
GridKeyDownEvent,
|
GridKeyDownEvent,
|
||||||
GridRowContextMenuEvent,
|
GridRowContextMenuEvent,
|
||||||
} from '@/components/grid/grid-event.js';
|
} from '@/components/grid/grid-event.js';
|
||||||
import { GridColumnSetting } from '@/components/grid/column.js';
|
|
||||||
import { DroppedFile, extractDroppedItems, flattenDroppedFiles } from '@/scripts/file-drop.js';
|
import { DroppedFile, extractDroppedItems, flattenDroppedFiles } from '@/scripts/file-drop.js';
|
||||||
import { optInGridUtils } from '@/components/grid/optin-utils.js';
|
import { optInGridUtils } from '@/components/grid/optin-utils.js';
|
||||||
import XRegisterLogs from '@/pages/admin/custom-emojis-grid.local.logs.vue';
|
import XRegisterLogs from '@/pages/admin/custom-emojis-grid.local.logs.vue';
|
||||||
|
import { GridSetting } from '@/components/grid/grid.js';
|
||||||
|
|
||||||
const MAXIMUM_EMOJI_REGISTER_COUNT = 100;
|
const MAXIMUM_EMOJI_REGISTER_COUNT = 100;
|
||||||
|
|
||||||
|
@ -125,18 +121,34 @@ type GridItem = {
|
||||||
roleIdsThatCanBeUsedThisEmojiAsReaction: string;
|
roleIdsThatCanBeUsedThisEmojiAsReaction: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const required = validators.required();
|
function setupGrid(): GridSetting {
|
||||||
const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
|
const required = validators.required();
|
||||||
const columnSettings: GridColumnSetting[] = [
|
const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
|
||||||
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto', validators: [required] },
|
|
||||||
{ bindTo: 'name', title: 'name', type: 'text', editable: true, width: 140, validators: [required, regex] },
|
return {
|
||||||
{ bindTo: 'category', title: 'category', type: 'text', editable: true, width: 140 },
|
row: {
|
||||||
{ bindTo: 'aliases', title: 'aliases', type: 'text', editable: true, width: 140 },
|
showNumber: true,
|
||||||
{ bindTo: 'license', title: 'license', type: 'text', editable: true, width: 140 },
|
selectable: true,
|
||||||
{ bindTo: 'isSensitive', title: 'sensitive', type: 'boolean', editable: true, width: 90 },
|
minimumDefinitionCount: 100,
|
||||||
{ bindTo: 'localOnly', title: 'localOnly', type: 'boolean', editable: true, width: 90 },
|
styleRules: [
|
||||||
{ bindTo: 'roleIdsThatCanBeUsedThisEmojiAsReaction', title: 'role', type: 'text', editable: true, width: 100 },
|
{
|
||||||
];
|
condition: ({ cells }) => cells.some(it => !it.violation.valid),
|
||||||
|
applyStyle: { className: 'violationRow' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
cols: [
|
||||||
|
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto', validators: [required] },
|
||||||
|
{ bindTo: 'name', title: 'name', type: 'text', editable: true, width: 140, validators: [required, regex] },
|
||||||
|
{ bindTo: 'category', title: 'category', type: 'text', editable: true, width: 140 },
|
||||||
|
{ bindTo: 'aliases', title: 'aliases', type: 'text', editable: true, width: 140 },
|
||||||
|
{ bindTo: 'license', title: 'license', type: 'text', editable: true, width: 140 },
|
||||||
|
{ bindTo: 'isSensitive', title: 'sensitive', type: 'boolean', editable: true, width: 90 },
|
||||||
|
{ bindTo: 'localOnly', title: 'localOnly', type: 'boolean', editable: true, width: 90 },
|
||||||
|
{ bindTo: 'roleIdsThatCanBeUsedThisEmojiAsReaction', title: 'role', type: 'text', editable: true, width: 100 },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const uploadFolders = ref<FolderItem[]>([]);
|
const uploadFolders = ref<FolderItem[]>([]);
|
||||||
const gridItems = ref<GridItem[]>([]);
|
const gridItems = ref<GridItem[]>([]);
|
||||||
|
@ -284,7 +296,7 @@ async function onFileSelectClicked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onDriveSelectClicked() {
|
async function onDriveSelectClicked() {
|
||||||
const driveFiles = await os.promiseDialog(chooseFileFromDrive(true));
|
const driveFiles = await chooseFileFromDrive(true);
|
||||||
gridItems.value.push(...driveFiles.map(fromDriveFile));
|
gridItems.value.push(...driveFiles.map(fromDriveFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,6 +394,12 @@ onMounted(async () => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.violationRow {
|
||||||
|
background-color: var(--infoWarnBg);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style module lang="scss">
|
<style module lang="scss">
|
||||||
.uploadBox {
|
.uploadBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
<div v-if="gridItems.length > 0">
|
<div v-if="gridItems.length > 0">
|
||||||
<div :class="$style.gridArea">
|
<div :class="$style.gridArea">
|
||||||
<MkGrid :data="gridItems" :columnSettings="columnSettings" @event="onGridEvent"/>
|
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="_gaps">
|
<div class="_gaps">
|
||||||
|
@ -65,6 +65,7 @@ import { optInGridUtils } from '@/components/grid/optin-utils.js';
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
import XRegisterLogs from '@/pages/admin/custom-emojis-grid.local.logs.vue';
|
import XRegisterLogs from '@/pages/admin/custom-emojis-grid.local.logs.vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
|
import { GridSetting } from '@/components/grid/grid.js';
|
||||||
|
|
||||||
type GridItem = {
|
type GridItem = {
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
|
@ -74,12 +75,16 @@ type GridItem = {
|
||||||
host: string;
|
host: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const columnSettings: GridColumnSetting[] = [
|
function setupGrid(): GridSetting {
|
||||||
{ bindTo: 'checked', icon: 'ti-download', type: 'boolean', editable: true, width: 34 },
|
return {
|
||||||
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto' },
|
cols: [
|
||||||
{ bindTo: 'name', title: 'name', type: 'text', editable: false, width: 'auto' },
|
{ bindTo: 'checked', icon: 'ti-download', type: 'boolean', editable: true, width: 34 },
|
||||||
{ bindTo: 'host', title: 'host', type: 'text', editable: false, width: 'auto' },
|
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto' },
|
||||||
];
|
{ bindTo: 'name', title: 'name', type: 'text', editable: false, width: 'auto' },
|
||||||
|
{ bindTo: 'host', title: 'host', type: 'text', editable: false, width: 'auto' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const requestLogs = ref<RequestLogItem[]>([]);
|
const requestLogs = ref<RequestLogItem[]>([]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue