Skip to content

Commit

Permalink
feat(data-validation): transform support for data validation (#1915)
Browse files Browse the repository at this point in the history
* feat: add-range & delete-range support spillable ref-range strategy

* feat: ref-range

* feat: move resource and sheet controller to data-validation pkg

* fix: unique editor id

* fix: eslint

* feat: lock

* fix: move-range

* fix: css

* feat: add ref-range tldr pic

* feat: test

* feat: ref-range unit testt

* fix: redi warning

* feat: lint

* feat: build

* feat: move mark-dirty mutation to dv-pkg

* feat: add dayjs default plugin

* feat: text-length i18n

* feat: rename ref-range util

* feat: rename

* feat: support data-validation transform

* feat: data-validation list support formula

* feat: remove useless code

* feat: dv-demo

* fix: build

* feat: delay load data validation resource on web app

* feat: build fix

* fix: build

* feat: lint

* feat: add unitId bind

* feat: subUnitId

* feat: update

* feat: update

* feat: update

* feat: update

* feat: update

* feat: update

* fix: empty range

* feat: update

* feat: add polyfill of old version

* feat: update

* feat: update

* feat: update

* feat: update

* feat: fix deps issue

* feat: style update

* feat: update

* feat: update

* feat: update

* feat: update

* feat: update

* feat: lock

* feat: build

* feat: temp

* feat: update

* feat: update

* feat: update

* feat: update

* feat: update

* feat: test

* feat: update

* fix: fix lockfile

* fix: popup

* feat: locale

* feat: lint

---------

Co-authored-by: 白熱 <sonne@asaki.me>
  • Loading branch information
weird94 and jikkai committed Apr 22, 2024
1 parent 8c3bb90 commit 22ccbb1
Show file tree
Hide file tree
Showing 24 changed files with 485 additions and 392 deletions.
174 changes: 174 additions & 0 deletions examples/src/data/sheets/demo/default-workbook-data-validation.ts
@@ -0,0 +1,174 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export const DEFAULT_WORKBOOK_DATA_VALIDATION = {
id: 'workbook-01',
sheetOrder: [
'80FIpJ1SdQLVIUEbrnC3J',
],
name: 'UniverSheet Demo',
appVersion: '3.0.0-alpha',
locale: 'zhCN',
styles: {},
sheets: {
'80FIpJ1SdQLVIUEbrnC3J': {
name: '工作表1',
id: '80FIpJ1SdQLVIUEbrnC3J',
tabColor: '',
hidden: 0,
rowCount: 1000,
columnCount: 20,
zoomRatio: 1,
freeze: {
xSplit: 0,
ySplit: 0,
startRow: -1,
startColumn: -1,
},
scrollTop: 0,
scrollLeft: 0,
defaultColumnWidth: 73,
defaultRowHeight: 19,
mergeData: [],
cellData: {
0: {
0: {
v: 'YES',
t: 1,
},
2: {
v: 'IF',
t: 1,
},
5: {
v: '中文',
t: 1,
},
6: {
v: '一',
t: 1,
},
7: {
v: '二',
t: 1,
},
8: {
v: '三',
t: 1,
},
},
1: {
5: {
v: '数字',
t: 1,
},
6: {
v: 1,
t: 2,
},
7: {
v: 2,
t: 2,
},
8: {
v: 3,
t: 2,
},
},
2: {
2: {
v: '级联',
t: 1,
},
3: {
v: '中文',
t: 1,
},
4: {
v: '一',
t: 1,
},
5: null,
6: null,
7: null,
8: null,
},
3: {
3: null,
4: null,
5: null,
6: null,
7: null,
8: null,
},
},
rowData: {
0: {
hd: 0,
h: 19,
ah: 20,
},
2: {
hd: 0,
h: 19,
ah: 20,
},
3: {
hd: 0,
h: 19,
ah: 19,
},
},
columnData: {},
showGridlines: 1,
rowHeader: {
width: 46,
hidden: 0,
},
columnHeader: {
height: 20,
hidden: 0,
},
selections: [
'A1',
],
rightToLeft: 0,
},
},
resources: [
{
name: 'SHEET_NUMFMT_PLUGIN',
data: '',
},
{
name: 'SHEET_DEFINED_NAME_PLUGIN',
data: '',
},
{
name: 'SHEET_DATA_VALIDATION',
data: '{"sheet-0011":[{"uid":"xxx-1","type":"decimal","ranges":[{"startRow":0,"endRow":5,"startColumn":0,"endColumn":2}],"operator":"greaterThan","formula1":"111","errorStyle":1},{"uid":"xxx-0","type":"date","ranges":[{"startRow":0,"endRow":5,"startColumn":3,"endColumn":5}],"operator":"greaterThan","formula1":"100","errorStyle":1},{"uid":"xxx-2","type":"checkbox","ranges":[{"startRow":6,"endRow":10,"startColumn":0,"endColumn":5}]},{"uid":"xxx-3","type":"list","ranges":[{"startRow":11,"endRow":15,"startColumn":0,"endColumn":5}],"formula1":"1,2,3,hahaha"},{"uid":"xxx-4","type":"custom","ranges":[{"startRow":16,"endRow":20,"startColumn":0,"endColumn":5}],"formula1":"=A1"},{"uid":"xxx-5","type":"listMultiple","ranges":[{"startRow":21,"endRow":21,"startColumn":0,"endColumn":0}],"formula1":"1,2,3,4,5,哈哈哈哈"}],"80FIpJ1SdQLVIUEbrnC3J":[{"uid":"pQCe2q","type":"list","formula1":"=IF(A1=\\"YES\\",G1:I1,G2:I2)","ranges":[{"startRow":0,"endRow":0,"startColumn":3,"endColumn":3}],"formula2":""},{"uid":"JL6foF","type":"list","formula1":"=F1:F2","ranges":[{"startRow":2,"startColumn":3,"endRow":2,"endColumn":3,"rangeType":0}],"formula2":""},{"uid":"XlFuI6","type":"list","formula1":"=IF(D3=\\"中文\\",G1:I1,G2:I2)","ranges":[{"startRow":2,"startColumn":4,"endRow":2,"endColumn":4,"rangeType":0}],"formula2":""}]}',
},
{
name: 'SHEET_CONDITIONAL_FORMATTING_PLUGIN',
data: '',
},
],
__env__: {
gitHash: '840580212',
gitBranch: 'feat/dv-list-formula',
buildTime: '2024-04-10T11:19:00.298Z',
},
};
1 change: 1 addition & 0 deletions packages/data-validation/package.json
Expand Up @@ -73,6 +73,7 @@
},
"devDependencies": {
"@univerjs/core": "workspace:*",
"@univerjs/protocol": "^0.1.14",
"@univerjs/shared": "workspace:*",
"@univerjs/sheets": "workspace:*",
"@wendellhu/redi": "^0.13.0",
Expand Down
Expand Up @@ -34,13 +34,7 @@ export const AddDataValidationMutation: ICommand<IAddDataValidationMutationParam
}
const { unitId, subUnitId, rule, index } = params;
const dataValidationModel = accessor.get(DataValidationModel);
if (Array.isArray(rule)) {
rule.forEach((ruleItem) => {
dataValidationModel.addRule(unitId, subUnitId, ruleItem, index);
});
} else {
dataValidationModel.addRule(unitId, subUnitId, rule!, index);
}
dataValidationModel.addRule(unitId, subUnitId, rule, index);

return true;
},
Expand Down
6 changes: 3 additions & 3 deletions packages/data-validation/src/common/util.ts
Expand Up @@ -14,11 +14,11 @@
* limitations under the License.
*/

import { DataValidationOperator, DataValidationType, type IDataValidationRule, type IDataValidationRuleBase, type IDataValidationRuleOptions, Tools } from '@univerjs/core';
import { DataValidationOperator, DataValidationType, type IDataValidationRuleBase, type IDataValidationRuleOptions, Tools } from '@univerjs/core';
import { SelectionManagerService } from '@univerjs/sheets';
import type { IAccessor } from '@wendellhu/redi';

export function getRuleSetting(rule: IDataValidationRule): IDataValidationRuleBase {
export function getRuleSetting(rule: IDataValidationRuleBase): IDataValidationRuleBase {
return {
type: rule.type,
operator: rule.operator,
Expand All @@ -28,7 +28,7 @@ export function getRuleSetting(rule: IDataValidationRule): IDataValidationRuleBa
};
}

export function getRuleOptions(rule: IDataValidationRule): IDataValidationRuleOptions {
export function getRuleOptions(rule: IDataValidationRuleOptions): IDataValidationRuleOptions {
return {
error: rule.error,
errorStyle: rule.errorStyle,
Expand Down
28 changes: 19 additions & 9 deletions packages/data-validation/src/models/data-validation-manager.ts
Expand Up @@ -19,6 +19,7 @@ import { DataValidationStatus, Disposable } from '@univerjs/core';
import { Subject } from 'rxjs';
import type { IUpdateRulePayload } from '../types/interfaces/i-update-rule-payload';
import { UpdateRuleType } from '../types/enum/update-rule-type';
import { getRuleOptions, getRuleSetting } from '../common/util';

export class DataValidationManager<T extends IDataValidationRule> extends Disposable {
private _dataValidations: T[];
Expand Down Expand Up @@ -66,22 +67,30 @@ export class DataValidationManager<T extends IDataValidationRule> extends Dispos
return this._dataValidations.findIndex((rule) => rule.uid === id);
}

addRule(rule: T, index?: number) {
addRule(rule: T | T[], index?: number) {
const _rules = Array.isArray(rule) ? rule : [rule];
const rules = _rules.filter((item) => !this._dataValidationMap.has(item.uid));

if (typeof index === 'number' && index < this._dataValidations.length) {
this._dataValidations.splice(index, 0, rule);
this._dataValidations.splice(index, 0, ...rules);
} else {
this._dataValidations.push(rule);
this._dataValidations.push(...rules);
}

this._dataValidationMap.set(rule.uid, rule);
rules.forEach((item) => {
this._dataValidationMap.set(item.uid, item);
});

this._notice();
}

removeRule(ruleId: string) {
const index = this._dataValidations.findIndex((item) => item.uid === ruleId);
this._dataValidations.splice(index, 1);
this._dataValidationMap.delete(ruleId);
this._notice();
if (index > -1) {
this._dataValidations.splice(index, 1);
this._dataValidationMap.delete(ruleId);
this._notice();
}
}

updateRule(ruleId: string, payload: IUpdateRulePayload) {
Expand All @@ -94,18 +103,19 @@ export class DataValidationManager<T extends IDataValidationRule> extends Dispos

const rule = { ...oldRule };


switch (payload.type) {
case UpdateRuleType.RANGE: {
rule.ranges = payload.payload;
break;
}
case UpdateRuleType.SETTING: {
Object.assign(rule, payload.payload);
Object.assign(rule, getRuleSetting(payload.payload));
break;
}

case UpdateRuleType.OPTIONS: {
Object.assign(rule, payload.payload);
Object.assign(rule, getRuleOptions(payload.payload));
break;
}
default:
Expand Down
43 changes: 29 additions & 14 deletions packages/data-validation/src/models/data-validation-model.ts
Expand Up @@ -78,16 +78,29 @@ export class DataValidationModel<T extends IDataValidationRule = IDataValidation
return manager;
}

addRule(unitId: string, subUnitId: string, rule: T, index?: number) {
private _addRuleSideEffect(unitId: string, subUnitId: string, rule: T) {
const manager = this.ensureManager(unitId, subUnitId);
const oldRule = manager.getRuleById(rule.uid);
if (oldRule) {
return;
}
this._ruleChange$.next({
rule,
type: 'add',
unitId,
subUnitId,
});
}

addRule(unitId: string, subUnitId: string, rule: T | T[], index?: number) {
try {
const manager = this.ensureManager(unitId, subUnitId);
manager.addRule(rule, index);
this._ruleChange$.next({
rule: rule as any,
type: 'add',
unitId,
subUnitId,
const rules = Array.isArray(rule) ? rule : [rule];
rules.forEach((item) => {
this._addRuleSideEffect(unitId, subUnitId, item);
});

manager.addRule(rule, index);
} catch (error) {
this._logService.error(error);
}
Expand All @@ -113,13 +126,15 @@ export class DataValidationModel<T extends IDataValidationRule = IDataValidation
try {
const manager = this.ensureManager(unitId, subUnitId);
const oldRule = manager.getRuleById(ruleId);
manager.removeRule(ruleId);
this._ruleChange$.next({
rule: oldRule,
type: 'remove',
unitId,
subUnitId,
});
if (oldRule) {
manager.removeRule(ruleId);
this._ruleChange$.next({
rule: oldRule,
type: 'remove',
unitId,
subUnitId,
});
}
} catch (error) {
this._logService.error(error);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/data-validation/src/plugin.ts
Expand Up @@ -23,7 +23,7 @@ import { AddDataValidationCommand, RemoveAllDataValidationCommand, RemoveDataVal
import { AddDataValidationMutation, RemoveDataValidationMutation, UpdateDataValidationMutation } from './commands/mutations/data-validation.mutation';
import { DataValidationResourceController } from './controllers/dv-resource.controller';
import { DataValidationSheetController } from './controllers/dv-sheet.controller';
import { DataValidationFormulaMarkDirty } from './commands/mutations/formula.mutation.ts';
import { DataValidationFormulaMarkDirty } from './commands/mutations/formula.mutation';

const PLUGIN_NAME = 'data-validation';

Expand Down
Expand Up @@ -29,6 +29,7 @@ export interface IFormulaInputProps {
subUnitId: string;
showError?: boolean;
validResult?: IFormulaValidResult;
ruleId: string;
}

export type FormulaInputType = React.ComponentType<IFormulaInputProps>;
Expand Up @@ -51,7 +51,6 @@ export function DraggableList<T = any>(props: IDraggableListProps<T>) {

return (
<ReactGridLayout
useCSSTransforms={false}
{...gridProps}
cols={12}
preventCollision={false}
Expand Down

0 comments on commit 22ccbb1

Please sign in to comment.