summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/grid/cell-validators.ts
blob: 949cab2ec6533ace0f4f8e9c91b2ac7ce74b3845 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * SPDX-FileCopyrightText: syuilo and misskey-project
 * SPDX-License-Identifier: AGPL-3.0-only
 */

import { CellValue, GridCell } from '@/components/grid/cell.js';
import { GridColumn } from '@/components/grid/column.js';
import { GridRow } from '@/components/grid/row.js';
import { i18n } from '@/i18n.js';

export type ValidatorParams = {
	column: GridColumn;
	row: GridRow;
	value: CellValue;
	allCells: GridCell[];
};

export type ValidatorResult = {
	valid: boolean;
	message?: string;
}

export type GridCellValidator = {
	name?: string;
	ignoreViolation?: boolean;
	validate: (params: ValidatorParams) => ValidatorResult;
}

export type ValidateViolation = {
	valid: boolean;
	params: ValidatorParams;
	violations: ValidateViolationItem[];
}

export type ValidateViolationItem = {
	valid: boolean;
	validator: GridCellValidator;
	result: ValidatorResult;
}

export function cellValidation(allCells: GridCell[], cell: GridCell, newValue: CellValue): ValidateViolation {
	const { column, row } = cell;
	const validators = column.setting.validators ?? [];

	const params: ValidatorParams = {
		column,
		row,
		value: newValue,
		allCells,
	};

	const violations: ValidateViolationItem[] = validators.map(validator => {
		const result = validator.validate(params);
		return {
			valid: result.valid,
			validator,
			result,
		};
	});

	return {
		valid: violations.every(v => v.result.valid),
		params,
		violations,
	};
}

class ValidatorPreset {
	required(): GridCellValidator {
		return {
			name: 'required',
			validate: ({ value }): ValidatorResult => {
				return {
					valid: value !== null && value !== undefined && value !== '',
					message: i18n.ts._gridComponent._error.requiredValue,
				};
			},
		};
	}

	regex(pattern: RegExp): GridCellValidator {
		return {
			name: 'regex',
			validate: ({ value }): ValidatorResult => {
				return {
					valid: (typeof value !== 'string') || pattern.test(value.toString() ?? ''),
					message: i18n.tsx._gridComponent._error.patternNotMatch({ pattern: pattern.source }),
				};
			},
		};
	}

	unique(): GridCellValidator {
		return {
			name: 'unique',
			validate: ({ column, row, value, allCells }): ValidatorResult => {
				const bindTo = column.setting.bindTo;
				const isUnique = allCells
					.filter(it => it.column.setting.bindTo === bindTo && it.row.index !== row.index)
					.every(cell => cell.value !== value);
				return {
					valid: isUnique,
					message: i18n.ts._gridComponent._error.notUnique,
				};
			},
		};
	}
}

export const validators = new ValidatorPreset();