add remove row function

This commit is contained in:
Sergey Krylov 2022-07-14 16:13:43 +05:00
parent 2f78b7ec22
commit 497a275537
11 changed files with 133 additions and 14 deletions

View File

@ -3,10 +3,10 @@ import * as actions from 'redux/action-creators';
import { $, Dom } from 'core/Dom';
import { ComponentOptionsType, ExcelComponent } from 'core/ExcelComponent';
import { TableSelection } from 'components/table/TableSelection';
import { changeCurrentStyles, changeCurrentText, changeTableSize } from 'redux/action-creators';
import { changeCurrentStyles, changeCurrentText, changeTableSize, removeRowFromTable } from 'redux/action-creators';
import { createTable, getNewRowHTML } from 'components/table/table.template';
import { initialState, initialStyleState } from 'src/constants';
import { parse } from 'core/utils';
import { getCellId, parse } from 'core/utils';
import { resizeHandler } from 'components/table/handlers/table.resize';
import { selectHandler } from 'components/table/handlers/table.select.handler';
@ -45,8 +45,8 @@ export class Table extends ExcelComponent {
const maxColFromState = Math.max(...Object.keys(colState).map(el => +el));
const normalTableSize = {
col: Math.max(maxRowFromState, row),
row: Math.max(maxColFromState, col),
row: Math.max(maxRowFromState, row),
col: Math.max(maxColFromState, col),
};
if ((maxColFromState !== this.tableSize.col) || (maxRowFromState !== this.tableSize.row)) {
@ -65,6 +65,7 @@ export class Table extends ExcelComponent {
this.$onEventFromObserver('formula:enter-press', () => this.selection.$currentCell.focus());
this.$onEventFromObserver('toolbar:applyStyle', this.updateCurrentStyles);
this.$onEventFromObserver('toolbar:add-row', this.addNewRowHandler);
this.$onEventFromObserver('toolbar:remove-row', this.removeRowHandler);
}
initTable() {
@ -156,7 +157,7 @@ export class Table extends ExcelComponent {
}));
};
updateCurrentStyles = (style: CSSStyleDeclaration) => {
updateCurrentStyles = (style: Partial<CSSStyleDeclaration>) => {
this.selection.applyStyle(style);
this.dispatchToStore(actions.applyStyle({
value: style,
@ -194,4 +195,17 @@ export class Table extends ExcelComponent {
onMouseup() {
this.isMouseDowned = false;
}
removeRowHandler = () => {
const cell = this.selection.$focusedCell;
const cellId = getCellId(cell);
if (!cellId) return;
const { row } = cellId;
const nodeToRemove = this.$root.find(`[data-row='${row}']`);
this.$root.removeChild(nodeToRemove);
this.selection.clearSelection();
this.dispatchToStore(removeRowFromTable(+row));
};
}

View File

@ -1,6 +1,7 @@
import { Table } from 'components/table/Table';
import { $, Dom } from 'core/Dom';
import { getParamsFromCellId, startCellId } from 'components/table/table.functions';
import { initialStyleState } from 'src/constants';
export class TableSelection {
static selectedClassName = 'selected';
@ -60,6 +61,7 @@ export class TableSelection {
this.$currentCell?.removeClass(TableSelection.selectedClassName);
this.clearHeaderSelection();
this.selectedCellsGroup = [];
this.rootTable.updateCurrentStyles(initialStyleState);
}
selectFromTo($from: Dom, $cell: Dom) {
@ -110,7 +112,7 @@ export class TableSelection {
this.$currentCell = $cell;
}
applyStyle(style: CSSStyleDeclaration) {
applyStyle(style: Partial<CSSStyleDeclaration>) {
this.selectedCellsGroup.forEach(el => el.css(style));
}

View File

@ -71,6 +71,7 @@ export function selectHandler(event: MouseEvent | KeyboardEvent, selection: Tabl
switch (key) {
case 'ArrowDown': {
if (selection.rootTable.tableSize.row === row + 1) return;
row++;
break;
}
@ -79,6 +80,7 @@ export function selectHandler(event: MouseEvent | KeyboardEvent, selection: Tabl
break;
}
case 'ArrowRight': {
if (selection.rootTable.tableSize.col === col + 1) return;
col++;
break;
}

View File

@ -49,11 +49,16 @@ export class Toolbar extends ExcelComponentState {
// TODO refactor, make style handler
const target = $(event.target);
if (target.closest('[data-addbtn]').isExist) {
if (target.closest('[data-add-row-btn]').isExist) {
this.$emitEventToObserver('toolbar:add-row');
return;
}
if (target.closest('[data-remove-row-btn]').isExist) {
this.$emitEventToObserver('toolbar:remove-row');
return;
}
let stringValue;
let value;
let key;

View File

@ -88,7 +88,8 @@ export function createToolbar(state: ToolbarStateType): string {
buttons.push(increaseDecreaseFontSize);
buttons.push(selectGroup);
buttons.push(createAddRowTable());
buttons.push(createAddRowButton());
buttons.push(createRemoveRowButton());
return buttons.join('');
}
@ -170,10 +171,18 @@ function createButtonFromConfig(btnConfig: ButtonConfigType) {
`;
}
function createAddRowTable() {
function createAddRowButton() {
return `
<div class="button" data-addbtn>
<i class="material-icons" data-addbtn>add_circle</i>
<div class="button" data-add-row-btn>
<i class="material-icons" data-add-row-btn>add_circle</i>
</div>
`;
}
function createRemoveRowButton() {
return `
<div class="button" data-remove-row-btn>
<i class="material-icons" data-remove-row-btn>remove_circle</i>
</div>
`;
}

View File

@ -134,6 +134,10 @@ export class Dom implements DomClass {
return this.$el.getAttribute(name);
}
removeChild($child: Dom) {
this.$el.removeChild($child.$el);
}
get isExist(): boolean {
return !!this.$el;
}

View File

@ -1,3 +1,4 @@
import { Dom } from 'core/Dom';
import { CallbackType, StateType } from 'redux/types';
import { fontSizes } from 'src/constants';
@ -66,3 +67,11 @@ export function isSmallestFontSize(fontSize?: string): number | boolean {
export function getMethodNameByEventName(eventName: string): string {
return `on${capitalize(eventName)}`;
}
export function getCellId($cell: Dom): { row: string, col:string } | false {
if (!$cell.isExist) return false;
const id = $cell.data.id?.split(':');
if (!Array.isArray(id)) return false;
const [row, col] = id;
return { row, col };
}

View File

@ -7,3 +7,4 @@ export const TABLE_RESIZE = 'TABLE_RESIZE';
export const UPDATE_DATE = 'UPDATE_DATE';
export const CHANGE_CURRENT_TEXT = 'CHANGE_CURRENT_TEXT';
export const CHANGE_TABLE_SIZE = 'CHANGE_TABLE_SIZE';
export const REMOVE_ROW_FROM_TABLE = 'REMOVE_ROW_FROM_TABLE';

View File

@ -7,7 +7,7 @@ import {
APPLY_STYLES,
CHANGE_TITLE,
DELETE_TABLE,
UPDATE_DATE, CHANGE_CURRENT_TEXT, CHANGE_TABLE_SIZE,
UPDATE_DATE, CHANGE_CURRENT_TEXT, CHANGE_TABLE_SIZE, REMOVE_ROW_FROM_TABLE,
} from 'redux/action-constants';
export function tableResize(resizeData: ResizeReturnDataType): ActionType {
@ -31,7 +31,7 @@ export function changeCurrentStyles(data: Partial<CSSStyleDeclaration>): ActionT
};
}
export function applyStyle(data: { ids: (string | undefined)[], value: CSSStyleDeclaration }): ActionType {
export function applyStyle(data: { ids: (string | undefined)[], value: Partial<CSSStyleDeclaration> }): ActionType {
return {
type: APPLY_STYLES,
data,
@ -72,3 +72,10 @@ export function changeTableSize(data: { col: number, row: number }): ActionType
data,
};
}
export function removeRowFromTable(removedRowNumber: number) {
return {
type: REMOVE_ROW_FROM_TABLE,
data: removedRowNumber,
};
}

View File

@ -1,3 +1,4 @@
import { ToolbarStateType } from 'components/toolbar/toolbar-types';
import { ActionType, StateType } from 'redux/types';
import { ActiveRoute } from 'core/routes/ActiveRoute';
import { storageName } from 'pages/ExcelPage';
@ -8,7 +9,7 @@ import {
APPLY_STYLES,
CHANGE_TITLE,
DELETE_TABLE,
UPDATE_DATE, CHANGE_CURRENT_TEXT, CHANGE_TABLE_SIZE,
UPDATE_DATE, CHANGE_CURRENT_TEXT, CHANGE_TABLE_SIZE, REMOVE_ROW_FROM_TABLE,
} from 'redux/action-constants';
export function rootReducer(state: StateType, action: ActionType): StateType {
@ -74,6 +75,70 @@ export function rootReducer(state: StateType, action: ActionType): StateType {
return { ...state, tableSize: action.data };
}
case REMOVE_ROW_FROM_TABLE: {
// needs to be redefined next params:
// rowState: { [k: number]: number };
// dataState: { [k: string]: string };
// stylesState: { [k: string]: ToolbarStateType };
// tableSize: { col: number, row: number }
const newRowStateEntries: [number, number][] = [];
const newDataStateEntries: [string, string][] = [];
const newStylesStateEntries: [string, ToolbarStateType][] = [];
// rowState change
Object.entries(state.rowState).forEach(([key, value]) => {
switch (true) {
case key < action.data:
newRowStateEntries.push([+key, value]);
break;
case key > action.data:
newRowStateEntries.push([+key - 1, value]);
break;
default: break;
}
});
const newRowState = Object.fromEntries(newRowStateEntries);
// dataState change
Object.entries(state.dataState).forEach(([key, value]) => {
const [row, col] = key.split(':');
switch (true) {
case row < action.data:
newDataStateEntries.push([key, value.toString()]);
break;
case row > action.data:
newDataStateEntries.push([`${+row - 1}:${col}`, value.toString()]);
break;
default: break;
}
});
const newDataState = Object.fromEntries(newDataStateEntries);
// stylesState change
Object.entries(state.stylesState).forEach(([key, value]) => {
const [row, col] = key.split(':');
switch (true) {
case row < action.data:
newStylesStateEntries.push([key, value]);
break;
case row > action.data:
newStylesStateEntries.push([`${+row - 1}:${col}`, value]);
break;
default: break;
}
});
const newStylesState = Object.fromEntries(newStylesStateEntries);
// tableSize
const newTableSize = { col: state.tableSize.col, row: state.tableSize.row - 1 };
// const newRowState = Object.keys(state.rowState).filter(rowIndex => rowIndex.toString() !== action.data.toString()).
return { ...state, rowState: newRowState, dataState: newDataState, stylesState: newStylesState, tableSize: newTableSize };
}
default: return state;
}
}

View File

@ -5,6 +5,7 @@
position: absolute;
left: 0;
right: 0;
max-height: calc(100vh - ($header-height + $toolbar-height + $formula-height));
top: $header-height + $toolbar-height + $formula-height;
overflow: auto;
font-size: $default-cell-font-size;