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 = conditionList.reduce( (map, item) => { map[item.value] = item; return map; }, {} as Record, ); type FieldConditions = Partial>; 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> = { TIME: 'time', DATE: 'date', DATETIME: 'datetime', CREATED_TIME: 'datetime', UPDATED_TIME: 'datetime', }; const MultiChoiceComponent: Partial> = { 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 = dateFuncList.reduce( (map, item) => { map[item.key] = item; return map; }, {} as Record, ); export const getDateFuncList = (hasTime: boolean) => { return dateFuncList.filter((item) => { return item.condition ? item.condition === (hasTime ? 'datetime' : 'date') : true; }); };