This commit is contained in:
196
src/js/conditions.ts
Normal file
196
src/js/conditions.ts
Normal file
@@ -0,0 +1,196 @@
|
||||
import type { FieldsInfo } from '@/types/model';
|
||||
import { isType, type FieldType, type OneOf } from './kintone-rest-api-client';
|
||||
import { getFieldObj } from './helper';
|
||||
|
||||
// conditionValue = '' | 'eq' | 'ne'
|
||||
// conditionItem = { value: 'eq', label: '=(等しい)', type: 'input', func: (a: string, b: string) => a === b }
|
||||
// = conditionMap[conditionValue]
|
||||
export type ConditionValue = '' | '=' | '!=' | '>=' | '<=' | '<' | '>' | 'like' | 'not like' | 'in' | 'not in';
|
||||
|
||||
type ConditionItem = {
|
||||
value: ConditionValue;
|
||||
label: string | ((field: OneOf) => string);
|
||||
type: ComponentType | ((field: OneOf) => ComponentType);
|
||||
};
|
||||
|
||||
export const conditionList: ConditionItem[] = [
|
||||
{ value: '=', label: '=(等しい)', type: (field) => dateTimeComponent[field.type] || 'input' },
|
||||
{ value: '!=', label: '≠ (等しくない)', type: (field) => dateTimeComponent[field.type] || 'input' },
|
||||
{
|
||||
value: '<=',
|
||||
label: (field) => (isDateTimeType(field) ? '≦ (以前)' : '≦ (以下)'),
|
||||
type: (field) => dateTimeComponent[field.type] || 'input',
|
||||
},
|
||||
{ value: '<', label: '< (より前)', type: (field) => dateTimeComponent[field.type] || 'input' },
|
||||
{
|
||||
value: '>=',
|
||||
label: (field) => (isDateTimeType(field) ? '≧ (以降)' : '≧ (以上)'),
|
||||
type: (field) => dateTimeComponent[field.type] || 'input',
|
||||
},
|
||||
{ value: '>', label: '> (より後)', type: (field) => dateTimeComponent[field.type] || 'input' },
|
||||
{ value: 'like', label: '次のキーワードを含む', type: 'input' },
|
||||
{ value: 'not like', label: '次のキーワードを含まない', type: 'input' },
|
||||
{ value: 'in', label: '次のいずれかを含む', type: (field) => MultiChoiceComponent[field.type] || 'input' },
|
||||
{ value: 'not in', label: '次のいずれも含まない', type: (field) => MultiChoiceComponent[field.type] || 'input' },
|
||||
];
|
||||
|
||||
// search from conditionList
|
||||
// conditionItem = conditionMap[conditionValue]
|
||||
export const conditionMap: Record<ConditionValue, ConditionItem> = conditionList.reduce(
|
||||
(map, item) => {
|
||||
map[item.value] = item;
|
||||
return map;
|
||||
},
|
||||
{} as Record<ConditionValue, ConditionItem>,
|
||||
);
|
||||
|
||||
type FieldConditions = Partial<Record<FieldType, ConditionValue[]>>;
|
||||
const textCondition: ConditionValue[] = ['=', '!=', 'in', 'like', 'not like'];
|
||||
const numberCondition: ConditionValue[] = ['=', '!=', '<=', '>='];
|
||||
const timeCondition: ConditionValue[] = ['=', '!=', '<=', '>=', '<', '>'];
|
||||
const containsCondition: ConditionValue[] = ['in', 'not in'];
|
||||
|
||||
// FieldType -> ConditionValue[]
|
||||
const fieldConditions: FieldConditions = {
|
||||
SINGLE_LINE_TEXT: textCondition,
|
||||
MULTI_LINE_TEXT: containsCondition,
|
||||
RICH_TEXT: containsCondition,
|
||||
NUMBER: numberCondition,
|
||||
CHECK_BOX: containsCondition,
|
||||
RADIO_BUTTON: containsCondition,
|
||||
DROP_DOWN: containsCondition,
|
||||
MULTI_SELECT: containsCondition,
|
||||
USER_SELECT: containsCondition,
|
||||
ORGANIZATION_SELECT: containsCondition,
|
||||
GROUP_SELECT: containsCondition,
|
||||
LINK: textCondition,
|
||||
CALC: numberCondition,
|
||||
|
||||
TIME: timeCondition,
|
||||
DATE: timeCondition,
|
||||
DATETIME: timeCondition,
|
||||
CREATED_TIME: timeCondition,
|
||||
CREATOR: containsCondition,
|
||||
UPDATED_TIME: timeCondition,
|
||||
MODIFIER: containsCondition,
|
||||
RECORD_NUMBER: numberCondition,
|
||||
} as const;
|
||||
|
||||
// fieldCode -> conditionList: ConditionItem[]
|
||||
export const getAvailableCondition = (fieldCode: string, fieldsInfo: FieldsInfo, subTableCode: string | '') => {
|
||||
if (!fieldCode || !fieldsInfo.fields) return;
|
||||
const fieldObj = getFieldObj(fieldCode, fieldsInfo, '');
|
||||
if (!fieldObj) return;
|
||||
const conditions = fieldConditions[fieldObj.type] || textCondition; // TODO a fallback here
|
||||
return conditions.map((condition) => {
|
||||
const res = { ...conditionMap[condition] };
|
||||
res.label = typeof res.label === 'function' ? res.label(fieldObj) : res.label;
|
||||
return res;
|
||||
});
|
||||
};
|
||||
|
||||
const component = {
|
||||
input: 'kuc-text',
|
||||
select: 'kuc-combobox',
|
||||
time: 'kuc-time',
|
||||
date: 'date',
|
||||
datetime: 'datetime',
|
||||
multiChoice: 'kuc-multichoice',
|
||||
multiInput: 'multi-input',
|
||||
};
|
||||
|
||||
export const isDateTimeType = (field: OneOf) => {
|
||||
return field.type in dateTimeComponent;
|
||||
};
|
||||
|
||||
const dateTimeComponent: Partial<Record<FieldType, ComponentType>> = {
|
||||
TIME: 'time',
|
||||
DATE: 'date',
|
||||
DATETIME: 'datetime',
|
||||
CREATED_TIME: 'datetime',
|
||||
UPDATED_TIME: 'datetime',
|
||||
};
|
||||
|
||||
const MultiChoiceComponent: Partial<Record<FieldType, ComponentType>> = {
|
||||
CHECK_BOX: 'multiChoice',
|
||||
DROP_DOWN: 'multiChoice',
|
||||
RADIO_BUTTON: 'multiChoice',
|
||||
MULTI_SELECT: 'multiChoice',
|
||||
SINGLE_LINE_TEXT: 'multiInput',
|
||||
LINK: 'multiInput',
|
||||
};
|
||||
|
||||
export type ComponentType = keyof typeof component;
|
||||
export const getComponent = (value: ConditionValue, fieldObj: OneOf) => {
|
||||
if (!value || !fieldObj) return;
|
||||
const condition = conditionMap[value].type;
|
||||
return component[typeof condition === 'function' ? condition(fieldObj) : condition];
|
||||
};
|
||||
|
||||
type DateFuncItem = {
|
||||
value: string;
|
||||
label: string | ((isTime: boolean) => string);
|
||||
condition?: 'datetime' | 'date';
|
||||
key: DateFuncKey;
|
||||
};
|
||||
|
||||
export type DateFuncKey =
|
||||
| ''
|
||||
| 'FROM_TODAY'
|
||||
| '---NOW---'
|
||||
| 'NOW'
|
||||
| '---DAY---'
|
||||
| 'YESTERDAY'
|
||||
| 'TODAY'
|
||||
| 'TOMORROW'
|
||||
| '---WEEK---'
|
||||
| 'LAST_WEEK'
|
||||
| 'THIS_WEEK'
|
||||
| 'NEXT_WEEK'
|
||||
| '---MONTH---'
|
||||
| 'LAST_MONTH'
|
||||
| 'THIS_MONTH'
|
||||
| 'NEXT_MONTH'
|
||||
| '---YEAR---'
|
||||
| 'LAST_YEAR'
|
||||
| 'THIS_YEAR'
|
||||
| 'NEXT_YEAR';
|
||||
|
||||
export const dateFuncList: DateFuncItem[] = [
|
||||
{ key: '', value: '%s', label: (isTime) => (isTime ? '日時を指定' : '日付を指定') },
|
||||
{ key: 'FROM_TODAY', value: 'FROM_TODAY(%d, %s)', label: '今日から' },
|
||||
{ key: '---NOW---', value: '\---NOW---', label: '' },
|
||||
{ key: 'NOW', value: 'NOW()', label: '当時刻', condition: 'datetime' },
|
||||
{ key: '---DAY---', value: '\---DAY---', label: '', condition: 'datetime' },
|
||||
{ key: 'YESTERDAY', value: 'YESTERDAY()', label: '昨日' },
|
||||
{ key: 'TODAY', value: 'TODAY()', label: '今日' },
|
||||
{ key: 'TOMORROW', value: 'TOMORROW()', label: '明日' },
|
||||
{ key: '---WEEK---', value: '\---WEEK---', label: '' },
|
||||
{ key: 'LAST_WEEK', value: 'LAST_WEEK(%s)', label: '先週' },
|
||||
{ key: 'THIS_WEEK', value: 'THIS_WEEK(%s)', label: '今週' },
|
||||
{ key: 'NEXT_WEEK', value: 'NEXT_WEEK(%s)', label: '来週' },
|
||||
{ key: '---MONTH---', value: '\---MONTH---', label: '' },
|
||||
{ key: 'LAST_MONTH', value: 'LAST_MONTH(%s)', label: '先月' },
|
||||
{ key: 'THIS_MONTH', value: 'THIS_MONTH(%s)', label: '今月' },
|
||||
{ key: 'NEXT_MONTH', value: 'NEXT_MONTH(%s)', label: '来月' },
|
||||
{ key: '---YEAR---', value: '\---YEAR---', label: '' },
|
||||
{ key: 'LAST_YEAR', value: 'LAST_YEAR()', label: '昨年' },
|
||||
{ key: 'THIS_YEAR', value: 'THIS_YEAR()', label: '今年' },
|
||||
{ key: 'NEXT_YEAR', value: 'NEXT_YEAR()', label: '来年' },
|
||||
];
|
||||
|
||||
// search from dateFuncList
|
||||
// DateFuncItem = dateFuncMap[DateFuncKey]
|
||||
export const dateFuncMap: Record<DateFuncKey, DateFuncItem> = dateFuncList.reduce(
|
||||
(map, item) => {
|
||||
map[item.key] = item;
|
||||
return map;
|
||||
},
|
||||
{} as Record<DateFuncKey, DateFuncItem>,
|
||||
);
|
||||
|
||||
export const getDateFuncList = (hasTime: boolean) => {
|
||||
return dateFuncList.filter((item) => {
|
||||
return item.condition ? item.condition === (hasTime ? 'datetime' : 'date') : true;
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user