finish join/mapping

This commit is contained in:
2025-01-26 01:11:38 +08:00
parent 662b18548f
commit 62ec4b84fc
9 changed files with 178 additions and 179 deletions

View File

@@ -17,7 +17,7 @@ const props = defineProps<{
const savedData = inject<SavedData>('savedData') as SavedData; const savedData = inject<SavedData>('savedData') as SavedData;
const cachedData = inject<CachedData>('cachedData') as CachedData; const cachedData = inject<CachedData>('cachedData') as CachedData;
const selectedAppData = inject<CachedSelectedAppData>('selectedAppData') as CachedSelectedAppData; const selectedAppData = inject<CachedSelectedAppData>('selectedAppData') as CachedSelectedAppData;
const table = computed(() => selectedAppData.table.table); // const table = computed(() => selectedAppData.table.table);
const columns = reactive([ const columns = reactive([
{ {
@@ -31,7 +31,7 @@ const columns = reactive([
const vnode = h(TableCombobox, { const vnode = h(TableCombobox, {
items: computed(() => items: computed(() =>
getFieldsDropdownItems(selectedAppData.appFields, { getFieldsDropdownItems(selectedAppData.appFields, {
subTableCode: table.value, subTableCode: '', //table.value,
baseFilter: undefined, baseFilter: undefined,
defaultLabel: 'すべてのレコード', defaultLabel: 'すべてのレコード',
}), }),

View File

@@ -6,7 +6,7 @@
import type { CachedData, CachedSelectedAppData, FieldsJoinMapping, WhereCondition } from '@/types/model'; import type { CachedData, CachedSelectedAppData, FieldsJoinMapping, WhereCondition } from '@/types/model';
import { defineProps, inject, computed, reactive, render, h } from 'vue'; import { defineProps, inject, computed, reactive, render, h } from 'vue';
import { generateId, getFieldObj, getFieldsDropdownItems, search } from '@/js/helper'; import { generateId, getFieldObj, getFieldsDropdownItems, search } from '@/js/helper';
import { getLeftAvailableJoinType, getRightAvailableJoinType, isForceDisable } from '@/js/join'; import { getLeftAvailableJoinType, getRightAvailableJoinType, isLeftJoinForceDisable, isRightJoinForceDisable, } from '@/js/join';
import { getLeftAvailableMappingType, getRightAvailableMappingType } from '@/js/mapping'; import { getLeftAvailableMappingType, getRightAvailableMappingType } from '@/js/mapping';
import TableCombobox from './TableCombobox.vue'; import TableCombobox from './TableCombobox.vue';
import { type FieldType, type OneOf } from '@/js/kintone-rest-api-client'; import { type FieldType, type OneOf } from '@/js/kintone-rest-api-client';
@@ -23,10 +23,12 @@ const table = computed(() => selectedAppData.table.table);
const filterFunc = { const filterFunc = {
connect: { connect: {
subTable: table,
left: (right?: OneOf | '') => getLeftAvailableJoinType(right), left: (right?: OneOf | '') => getLeftAvailableJoinType(right),
right: (left?: OneOf | '') => getRightAvailableJoinType(left), right: (left?: OneOf | '') => getRightAvailableJoinType(left),
}, },
mapping: { mapping: {
subTable: computed(() => ''),
left: (right?: OneOf | '') => getLeftAvailableMappingType(right), left: (right?: OneOf | '') => getLeftAvailableMappingType(right),
right: (left?: OneOf | '') => getRightAvailableMappingType(left), right: (left?: OneOf | '') => getRightAvailableMappingType(left),
}, },
@@ -45,11 +47,11 @@ const columns = reactive([
items: computed(() => { items: computed(() => {
const dependFilterField = getField('rightField', rowData.id); const dependFilterField = getField('rightField', rowData.id);
return getFieldsDropdownItems(selectedAppData.appFields, { return getFieldsDropdownItems(selectedAppData.appFields, {
subTableCode: table.value, subTableCode: filterFunc[props.type].subTable.value,
baseFilter: filterFunc[props.type].left() as FieldType[], baseFilter: filterFunc[props.type].left() as FieldType[],
filterType: filterFunc[props.type].left(dependFilterField), filterType: filterFunc[props.type].left(dependFilterField),
dependFilterField, dependFilterField,
defaultDisableCallback: isForceDisable, defaultDisableCallback: isLeftJoinForceDisable,
}); });
}), }),
modelValue: computed(() => (search(props.modelValue, rowData.id) as FieldsJoinMapping)?.leftField || ''), modelValue: computed(() => (search(props.modelValue, rowData.id) as FieldsJoinMapping)?.leftField || ''),
@@ -89,7 +91,7 @@ const columns = reactive([
baseFilter: filterFunc[props.type].right() as FieldType[], baseFilter: filterFunc[props.type].right() as FieldType[],
filterType: filterFunc[props.type].right(dependFilterField), filterType: filterFunc[props.type].right(dependFilterField),
dependFilterField, dependFilterField,
defaultDisableCallback: isForceDisable, defaultDisableCallback: props.type === 'connect' ? isRightJoinForceDisable : undefined,
}); });
}), }),
modelValue: computed(() => (search(props.modelValue, rowData.id) as FieldsJoinMapping)?.rightField || ''), modelValue: computed(() => (search(props.modelValue, rowData.id) as FieldsJoinMapping)?.rightField || ''),
@@ -112,7 +114,7 @@ function getField(key: 'leftField' | 'rightField', id: string) {
const dataRow = search(props.modelValue, id) as FieldsJoinMapping | undefined; const dataRow = search(props.modelValue, id) as FieldsJoinMapping | undefined;
const fieldCode = dataRow ? dataRow[key] || '' : ''; const fieldCode = dataRow ? dataRow[key] || '' : '';
const targetFieldMap = key === 'leftField' ? selectedAppData.appFields : cachedData.currentAppFields; const targetFieldMap = key === 'leftField' ? selectedAppData.appFields : cachedData.currentAppFields;
const targetTable = key === 'leftField' ? table.value : ''; const targetTable = key === 'leftField' ? filterFunc[props.type].subTable.value : '';
return getFieldObj(fieldCode, targetFieldMap, targetTable); return getFieldObj(fieldCode, targetFieldMap, targetTable);
} }
</script> </script>

View File

@@ -1,5 +1,6 @@
<template> <template>
<kuc-combobox <kuc-combobox
className="kuc-text-input"
:items="items.value" :items="items.value"
:value="modelValue.value" :value="modelValue.value"
@change="updateValue" @change="updateValue"

View File

@@ -2,7 +2,7 @@
<kuc-combobox <kuc-combobox
v-if="items?.length" v-if="items?.length"
:items="items" :items="items"
:value="modelValue" :value="value"
@change="updateValue" @change="updateValue"
:disabled="selectedAppData.loading == undefined ? false : selectedAppData.loading" :disabled="selectedAppData.loading == undefined ? false : selectedAppData.loading"
/> />
@@ -14,7 +14,7 @@ import { search } from '@/js/helper';
import type { CachedSelectedAppData, WhereCondition } from '@/types/model'; import type { CachedSelectedAppData, WhereCondition } from '@/types/model';
import type { KucEvent } from '@/types/my-kintone'; import type { KucEvent } from '@/types/my-kintone';
import type { ComboboxChangeEventDetail } from 'kintone-ui-component'; import type { ComboboxChangeEventDetail } from 'kintone-ui-component';
import { defineProps, defineEmits, computed } from 'vue'; import { defineProps, defineEmits, computed, watch, ref } from 'vue';
const props = defineProps<{ const props = defineProps<{
modelValue: string; modelValue: string;
@@ -25,7 +25,25 @@ const props = defineProps<{
const whereCondition = computed(() => search(props.whereConditions, props.id) as WhereCondition | undefined); const whereCondition = computed(() => search(props.whereConditions, props.id) as WhereCondition | undefined);
const items = computed(() => getAvailableCondition(whereCondition.value?.field || '', props.selectedAppData.appFields, props.selectedAppData.table.table)); const items = computed(() =>
getAvailableCondition(
whereCondition.value?.field || '',
props.selectedAppData.appFields,
props.selectedAppData.table.table,
),
);
const value = ref(props.modelValue);
watch(
() => items,
() => {
const option = items.value?.[0] || { value: '' };
value.value = option.value;
updateValue({ detail: option });
},
{ deep: true },
);
type EmitData = { type EmitData = {
obj?: WhereCondition; obj?: WhereCondition;

View File

@@ -11,7 +11,7 @@
/* config 页面 */ /* config 页面 */
#app { #app {
width: 60vw; width: 60vw;
min-width: 920px; min-width: 940px;
} }
/* 最上面的说明 */ /* 最上面的说明 */
@@ -27,7 +27,7 @@
/* laebl input 单行的情况 */ /* laebl input 单行的情况 */
.flex-row .kintoneplugin-label { .flex-row .kintoneplugin-label {
margin: 0; margin: 0;
width: 10em; width: 8.5em;
} }
/* 遮罩 */ /* 遮罩 */

View File

@@ -11,14 +11,12 @@ type ConditionItem = {
value: ConditionValue; value: ConditionValue;
label: string; label: string;
type: ComponentType; type: ComponentType;
func: (a: string, b: string) => boolean;
}; };
export const conditionList: ConditionItem[] = [ export const conditionList: ConditionItem[] = [
{ value: '', label: '--------', type: '', func: (a: string, b: string) => true }, { value: 'eq', label: '=(等しい)', type: 'input' },
{ value: 'eq', label: '=(等しい)', type: 'input', func: (a: string, b: string) => a === b }, { value: 'ne', label: '(等しくない)', type: 'input' },
{ value: 'ne', label: '≠ (等しくない)', type: 'input', func: (a: string, b: string) => a !== b }, { value: 'test', label: 'test combobox', type: 'select' },
{ value: 'test', label: 'test combobox', type: 'select', func: (a: string, b: string) => a < b },
]; ];
// search from conditionList // search from conditionList
@@ -42,9 +40,9 @@ const fieldConditions: FieldConditions = {
// fieldCode -> conditionList: ConditionItem[] // fieldCode -> conditionList: ConditionItem[]
export const getAvailableCondition = (fieldCode: string, fieldsInfo: FieldsInfo, subTableCode: string | '') => { export const getAvailableCondition = (fieldCode: string, fieldsInfo: FieldsInfo, subTableCode: string | '') => {
if (!fieldCode || !fieldsInfo.fields) return; if (!fieldCode || !fieldsInfo.fields) return;
const fieldObj = getFieldObj(fieldCode, fieldsInfo, subTableCode); const fieldObj = getFieldObj(fieldCode, fieldsInfo, '');
if (!fieldObj) return; if (!fieldObj) return;
const conditions = fieldConditions[fieldObj.type] || []; const conditions = fieldConditions[fieldObj.type] || ['eq']; // TODO a mock here
return conditions.map((condition) => conditionMap[condition]); return conditions.map((condition) => conditionMap[condition]);
}; };

View File

@@ -1,99 +1,135 @@
import type { CalcType, LinkType } from '@/types/my-kintone'; import type { CalcType, LinkProtocolType } from '@/types/my-kintone';
import { isType, type FieldType, type OneOf } from './kintone-rest-api-client'; import { isType, type FieldType, type OneOf } from './kintone-rest-api-client';
import { KintoneFormFieldProperty } from '@kintone/rest-api-client';
export function isForceDisable(field: OneOf) { export function isLeftJoinForceDisable(field: OneOf) {
if (isType.CALC(field)) { if (isType.CALC(field)) {
return field.format === 'DAY_HOUR_MINUTE' || field.format === 'HOUR_MINUTE'; return field.format === 'DAY_HOUR_MINUTE' || field.format === 'HOUR_MINUTE';
} }
return false; return false;
} }
export function isRightJoinForceDisable(field: OneOf) {
if (isLookup(field)) {
return true;
}
return false;
}
export type SpecialType<T = string, F = any> = { export type SpecialType<T = string, F = any> = {
type: T; type: T;
format: F; format: F;
check: (field: OneOf, depField?: OneOf) => boolean; check: (checkField: OneOf, selectedField?: OneOf) => boolean;
}; };
// LEFT // LEFT
export type LeftCalcJoinType = SpecialType<'CALC_JOIN_FOR_LEFT', Record<CalcType, FieldType[]>>; // LEFT - lookup
export type LookupTypeL2R = SpecialType<'LOOKUP_FROM_LEFT', FieldType[]>;
export const forMayLookup = (format: FieldType[]): LookupTypeL2R => {
return {
type: 'LOOKUP_FROM_LEFT',
format,
check: function (checkField: OneOf, selectedLeftField?: OneOf) {
if (isLookup(checkField) && selectedLeftField) {
return isLookup(selectedLeftField) ? checkField.type === selectedLeftField.type : false;
}
return !!this.format?.find((e) => e === checkField.type);
},
};
};
export const calcJoinType: LeftCalcJoinType = { export const mayLookupText = forMayLookup(['SINGLE_LINE_TEXT']);
type: 'CALC_JOIN_FOR_LEFT', export const mayLookupNumber = forMayLookup(['NUMBER']);
export const mayLookupTextNumber = forMayLookup(['SINGLE_LINE_TEXT', 'NUMBER']);
// LEFT - calc
export type CalcTypeL2R = SpecialType<'CALC_FROM_LEFT', Record<CalcType, Array<FieldType | LookupTypeL2R>>>;
export const leftCalcType: CalcTypeL2R = {
type: 'CALC_FROM_LEFT',
format: { format: {
NUMBER: ['SINGLE_LINE_TEXT', 'NUMBER'], NUMBER: [mayLookupTextNumber],
NUMBER_DIGIT: ['SINGLE_LINE_TEXT', 'NUMBER'], NUMBER_DIGIT: [mayLookupTextNumber],
DATE: ['DATE'], DATE: ['DATE'],
TIME: ['TIME'], TIME: ['TIME'],
DATETIME: ['DATETIME'], DATETIME: ['DATETIME'],
HOUR_MINUTE: [], HOUR_MINUTE: [],
DAY_HOUR_MINUTE: [], DAY_HOUR_MINUTE: [],
}, },
check: function (field: OneOf, rightField?: OneOf) { check: function (checkField: OneOf, selectedLeftField?: OneOf) {
let allowed: FieldType[] = []; let allowed: Array<FieldType | LookupTypeL2R> = [];
if (rightField && isType.CALC(rightField)) { if (selectedLeftField && isType.CALC(selectedLeftField)) {
allowed = this.format[rightField.format]; allowed = this.format[selectedLeftField.format];
} }
if (field && isType.CALC(field)) { return !!allowed.find((e) => {
return !!allowed.find((e) => e === field.format); if (isSpecialType(e) && isLookupFromLeft(e)) {
} return e.check(checkField, selectedLeftField);
return false; }
return e === checkField.type;
});
}, },
}; };
export type LinkJoinType = SpecialType<'LINK_JOIN', Record<LinkType, LinkType[]>>; // LEFT - link
export type LinkType = SpecialType<'LINK', Record<LinkProtocolType, LinkProtocolType[]>>;
// 入力値の種別が同じ場合のみ export const linkType: LinkType = {
export const linkJoinType: LinkJoinType = { type: 'LINK',
type: 'LINK_JOIN',
format: { format: {
// 入力値の種別が同じ場合のみ
WEB: ['WEB'], WEB: ['WEB'],
CALL: ['CALL'], CALL: ['CALL'],
MAIL: ['MAIL'], MAIL: ['MAIL'],
}, },
check: function (field: OneOf, dependField?: OneOf) { check: function (checkField: OneOf, selectedField?: OneOf) {
let allowed: LinkType[] = []; let allowed: LinkProtocolType[] = [];
if (dependField && isType.LINK(dependField)) { if (selectedField && isType.LINK(selectedField)) {
allowed = this.format[dependField.protocol]; allowed = this.format[selectedField.protocol];
} }
if (field && isType.LINK(field)) { if (checkField && isType.LINK(checkField)) {
return !!allowed.find((e) => e === field.protocol); return !!allowed.find((e) => e === checkField.protocol);
} }
return false; return false;
}, },
}; };
// LEFT - rule
export type AvailableRight = FieldType | CalcTypeL2R | LinkType | LookupTypeL2R;
const availableLeftJoinType = { const availableLeftJoinType = {
SINGLE_LINE_TEXT: ['SINGLE_LINE_TEXT'], SINGLE_LINE_TEXT: [mayLookupText],
NUMBER: ['NUMBER'], NUMBER: [mayLookupNumber],
CALC: [calcJoinType], CALC: [leftCalcType],
DATE: ['DATE'], DATE: ['DATE'],
TIME: ['TIME'], TIME: ['TIME'],
DATETIME: ['DATETIME'], DATETIME: ['DATETIME'],
LINK: [linkJoinType], LINK: [linkType],
} as Record<FieldType, Array<FieldType | LeftCalcJoinType | LinkJoinType>>; } as Record<FieldType, AvailableRight[]>;
// RIGHT // RIGHT - calc
export type RightCalcJoinType = SpecialType<'CALC_JOIN_FOR_RIGHT', CalcType[]>; export type CalcTypeR2L = SpecialType<'CALC_FROM_RIGHT', CalcType[]>;
export const forCalc = (format: CalcType[]): RightCalcJoinType => { export const forCalc = (format: CalcType[]): CalcTypeR2L => {
return { return {
type: 'CALC_JOIN_FOR_RIGHT', type: 'CALC_FROM_RIGHT',
format, format,
check: function (field: OneOf, leftField?: OneOf) { check: function (checkField: OneOf, selectedRightField?: OneOf) {
return isType.CALC(field) && !!this.format?.find((e) => e === field.format); return isType.CALC(checkField) && !!this.format?.find((e) => e === checkField.format);
}, },
}; };
}; };
// RIGHT - rule
export type AvailableLeft = FieldType | CalcTypeR2L | LinkType;
const availableRightJoinType = { const availableRightJoinType = {
SINGLE_LINE_TEXT: ['SINGLE_LINE_TEXT', forCalc(['NUMBER', 'NUMBER_DIGIT'])], SINGLE_LINE_TEXT: ['SINGLE_LINE_TEXT', forCalc(['NUMBER', 'NUMBER_DIGIT'])],
NUMBER: ['NUMBER', forCalc(['NUMBER', 'NUMBER_DIGIT'])], NUMBER: ['NUMBER', forCalc(['NUMBER', 'NUMBER_DIGIT'])],
DATE: ['DATE', forCalc(['DATE'])], DATE: ['DATE', forCalc(['DATE'])],
TIME: ['TIME', forCalc(['TIME'])], TIME: ['TIME', forCalc(['TIME'])],
DATETIME: ['DATETIME', forCalc(['DATETIME'])], DATETIME: ['DATETIME', forCalc(['DATETIME'])],
LINK: [linkJoinType], LINK: [linkType],
} as Record<FieldType, Array<FieldType | RightCalcJoinType | LinkJoinType>>; } as Record<FieldType, AvailableLeft[]>;
// methods
// undefined means all // undefined means all
export function getRightAvailableJoinType(left?: OneOf | '') { export function getRightAvailableJoinType(left?: OneOf | '') {
if (left === undefined) { if (left === undefined) {
@@ -114,14 +150,22 @@ export function isSpecialType(obj: FieldType | SpecialType): obj is SpecialType
return typeof obj === 'object' && !Array.isArray(obj) && 'type' in obj; return typeof obj === 'object' && !Array.isArray(obj) && 'type' in obj;
} }
export function isLinkJoinType(obj: SpecialType): obj is LinkJoinType { export function isLookupFromLeft(obj: SpecialType): obj is LookupTypeL2R {
return obj.type === 'LINK_JOIN'; return obj.type === 'LOOKUP_FROM_LEFT';
} }
export function isLeftCalcJoinType(obj: SpecialType): obj is LeftCalcJoinType { export function isLinkType(obj: SpecialType): obj is LinkType {
return obj.type === 'CALC_JOIN_FOR_LEFT'; return obj.type === 'LINK';
} }
export function isRightCalcJoinType(obj: SpecialType): obj is RightCalcJoinType { export function isCalcFromLeft(obj: SpecialType): obj is CalcTypeL2R {
return obj.type === 'CALC_JOIN_FOR_RIGHT'; return obj.type === 'CALC_FROM_LEFT';
}
export function isCalcFromRight(obj: SpecialType): obj is CalcTypeR2L {
return obj.type === 'CALC_FROM_RIGHT';
}
export function isLookup(field: OneOf): field is KintoneFormFieldProperty.Lookup {
return 'lookup' in field;
} }

View File

@@ -1,75 +1,26 @@
import type { CalcType, LinkType, SelectType } from '@/types/my-kintone'; import { type FieldType, type OneOf } from './kintone-rest-api-client';
import { isType, type FieldType, type OneOf } from './kintone-rest-api-client'; import {
import { calcJoinType, linkJoinType, type SpecialType, isSpecialType } from './join'; leftCalcType,
import { KintoneFormFieldProperty } from '@kintone/rest-api-client'; linkType,
type SpecialType,
// LEFT mayLookupTextNumber,
export type LeftLookupMappingType = SpecialType<'LOOKUP_MAPPING_FOR_LEFT', FieldType[]>; mayLookupText,
type AvailableRight,
export const lookupMappingType = (format: FieldType[]): LeftLookupMappingType => { type AvailableLeft,
return { isLookup,
type: 'LOOKUP_MAPPING_FOR_LEFT', forCalc,
format, type CalcTypeR2L,
check: function (field: OneOf, rightField?: OneOf) { isSpecialType,
if (rightField && isLookup(rightField) && !isLookup(field)) { } from './join';
return false; import type { SelectType } from '@/types/my-kintone';
}
return !!this.format?.find((e) => e === field.type);
},
};
};
const mayLookupText = lookupMappingType(['SINGLE_LINE_TEXT']);
const mayLookupNumber = lookupMappingType(['NUMBER']);
export type LeftCalcMappingType = SpecialType<
'CALC_MAPPING_FOR_LEFT',
Record<CalcType, Array<FieldType | LeftLookupMappingType>>
>;
// same as join
export const calcMappingType: LeftCalcMappingType = {
type: 'CALC_MAPPING_FOR_LEFT',
format: {
NUMBER: [mayLookupText, mayLookupNumber],
NUMBER_DIGIT: [mayLookupText, mayLookupNumber],
DATE: ['DATE'],
TIME: ['TIME'],
DATETIME: ['DATETIME'],
HOUR_MINUTE: [],
DAY_HOUR_MINUTE: [],
},
check: function (field: OneOf, rightField?: OneOf) {
let allowed: Array<FieldType | LeftLookupMappingType> = [];
if (rightField && isType.CALC(rightField)) {
allowed = this.format[rightField.format];
}
if (field && isType.CALC(field)) {
return !!allowed.find((e) => {
if (isSpecialType(e) && isLeftLookupMappingType(e)) {
return e.check(field, rightField);
}
return e === field.format
});
}
return false;
},
};
export type LinkMappingType = SpecialType<'LINK_MAPPING', Record<LinkType, LinkType[]>>;
// same as join
export const linkMappingType = {
...linkJoinType,
type: 'LINK_MAPPING',
} as LinkMappingType;
// LEFT - rule
const availableLeftMappingType = { const availableLeftMappingType = {
SINGLE_LINE_TEXT: [mayLookupText], SINGLE_LINE_TEXT: [mayLookupText],
MULTI_LINE_TEXT: ['MULTI_LINE_TEXT'], MULTI_LINE_TEXT: ['MULTI_LINE_TEXT'],
RICH_TEXT: ['RICH_TEXT'], RICH_TEXT: ['RICH_TEXT'],
NUMBER: [mayLookupNumber, mayLookupText], NUMBER: [mayLookupTextNumber],
CALC: [calcMappingType], CALC: [leftCalcType],
RADIO_BUTTON: ['RADIO_BUTTON'], RADIO_BUTTON: ['RADIO_BUTTON'],
CHECK_BOX: ['CHECK_BOX'], CHECK_BOX: ['CHECK_BOX'],
MULTI_SELECT: ['MULTI_SELECT'], // TODO 带选项字段报错 MULTI_SELECT: ['MULTI_SELECT'], // TODO 带选项字段报错
@@ -80,45 +31,43 @@ const availableLeftMappingType = {
DATE: ['DATE', 'DATETIME'], DATE: ['DATE', 'DATETIME'],
TIME: ['TIME'], TIME: ['TIME'],
DATETIME: ['DATETIME'], DATETIME: ['DATETIME'],
LINK: [linkMappingType, mayLookupText], LINK: [linkType, mayLookupText],
//LOOKUP //LOOKUP
RECORD_NUMBER: [mayLookupText, mayLookupNumber], RECORD_NUMBER: [mayLookupTextNumber],
CREATOR: ['USER_SELECT'], CREATOR: ['USER_SELECT'],
CREATED_TIME: ['DATETIME'], CREATED_TIME: ['DATETIME'],
MODIFIER: ['USER_SELECT'], MODIFIER: ['USER_SELECT'],
UPDATED_TIME: ['DATETIME'], UPDATED_TIME: ['DATETIME'],
} as Record<FieldType, Array<FieldType | LeftCalcMappingType | LinkMappingType | LeftLookupMappingType>>; } as Record<FieldType, AvailableRight[]>;
// RIGHT // RIGHT
export type RightCalcMappingType = SpecialType<'CALC_MAPPING_FOR_RIGHT', CalcType[]>; export type LookupTypeR2L = SpecialType<'LOOKUP_FROM_RIGHT', Array<FieldType | CalcTypeR2L>>;
export type RightLookupMappingType = SpecialType<'LOOKUP_MAPPING_FOR_RIGHT', FieldType[]>;
export const forCalc = (format: CalcType[]): RightCalcMappingType => { export const isSameLookupOr = (format: Array<FieldType | CalcTypeR2L>): LookupTypeR2L => {
return { return {
type: 'CALC_MAPPING_FOR_RIGHT', type: 'LOOKUP_FROM_RIGHT',
format, format,
check: function (field: OneOf, leftField?: OneOf) { check: function (checkField: OneOf, selectedRightField?: OneOf) {
return isType.CALC(field) && !!this.format?.find((e) => e === field.format); if (selectedRightField && isLookup(selectedRightField)) {
}, return isLookup(checkField) ? checkField.type === selectedRightField.type : false;
}; }
}; return !!this.format?.find((e) => {
if (isSpecialType(e)) {
export const forLookup = (format: FieldType[]): RightLookupMappingType => { return e.check(checkField, selectedRightField);
return { }
type: 'LOOKUP_MAPPING_FOR_RIGHT', return e === checkField.type;
format, });
check: function (field: OneOf, leftField?: OneOf) {
if (!isLookup(field)) return false;
return !!this.format?.find((e) => e === field.type);
}, },
}; };
}; };
const availableRightMappingType = { const availableRightMappingType = {
SINGLE_LINE_TEXT: ['SINGLE_LINE_TEXT', 'NUMBER', forCalc(['NUMBER', 'NUMBER_DIGIT']), 'LINK', 'RECORD_NUMBER'], SINGLE_LINE_TEXT: [
isSameLookupOr(['SINGLE_LINE_TEXT', 'NUMBER', forCalc(['NUMBER', 'NUMBER_DIGIT']), 'LINK', 'RECORD_NUMBER']),
],
MULTI_LINE_TEXT: ['MULTI_LINE_TEXT'], MULTI_LINE_TEXT: ['MULTI_LINE_TEXT'],
RICH_TEXT: ['RICH_TEXT'], RICH_TEXT: ['RICH_TEXT'],
NUMBER: ['NUMBER', forCalc(['NUMBER', 'NUMBER_DIGIT']), forLookup(['NUMBER']), 'RECORD_NUMBER'], NUMBER: [isSameLookupOr(['NUMBER', forCalc(['NUMBER', 'NUMBER_DIGIT']), 'RECORD_NUMBER'])],
RADIO_BUTTON: ['RADIO_BUTTON'], RADIO_BUTTON: ['RADIO_BUTTON'],
CHECK_BOX: ['CHECK_BOX'], CHECK_BOX: ['CHECK_BOX'],
MULTI_SELECT: ['MULTI_SELECT'], // TODO 带选项字段报错 MULTI_SELECT: ['MULTI_SELECT'], // TODO 带选项字段报错
@@ -129,9 +78,10 @@ const availableRightMappingType = {
DATE: ['DATE', forCalc(['DATE'])], DATE: ['DATE', forCalc(['DATE'])],
TIME: ['TIME', forCalc(['TIME'])], TIME: ['TIME', forCalc(['TIME'])],
DATETIME: ['DATE', 'DATETIME', forCalc(['DATETIME']), 'CREATED_TIME', 'UPDATED_TIME'], DATETIME: ['DATE', 'DATETIME', forCalc(['DATETIME']), 'CREATED_TIME', 'UPDATED_TIME'],
LINK: [linkMappingType], LINK: [linkType],
} as Record<FieldType, Array<FieldType | RightCalcMappingType | RightLookupMappingType | LinkMappingType>>; } as Record<FieldType, Array<AvailableLeft | LookupTypeR2L>>;
// methods
// undefined means all // undefined means all
export function getRightAvailableMappingType(left?: OneOf | '') { export function getRightAvailableMappingType(left?: OneOf | '') {
if (left === undefined) { if (left === undefined) {
@@ -148,14 +98,6 @@ export function getLeftAvailableMappingType(right?: OneOf | '') {
return right ? availableRightMappingType[right.type] : []; return right ? availableRightMappingType[right.type] : [];
} }
export function isLeftLookupMappingType(obj: SpecialType): obj is LeftLookupMappingType { export function isSelectType(field: OneOf): field is SelectType {
return obj.type === 'LOOKUP_MAPPING_FOR_LEFT'; return 'options' in field;
} }
export function isLookup(field: OneOf): field is KintoneFormFieldProperty.Lookup {
return 'lookup' in field;
}
// export function isSelectType(field: OneOf): field is SelectType {
// return 'options' in field;
// }

View File

@@ -1,20 +1,14 @@
import { KintoneFormFieldProperty } from '@kintone/rest-api-client';
export interface KucEvent<T> { export interface KucEvent<T> {
detail: T; detail: T;
} }
export type CalcType = 'NUMBER' | 'NUMBER_DIGIT' | 'DATETIME' | 'DATE' | 'TIME' | 'HOUR_MINUTE' | 'DAY_HOUR_MINUTE'; export type CalcType = 'NUMBER' | 'NUMBER_DIGIT' | 'DATETIME' | 'DATE' | 'TIME' | 'HOUR_MINUTE' | 'DAY_HOUR_MINUTE';
export type LinkType = 'WEB' | 'CALL' | 'MAIL'; export type LinkProtocolType = 'WEB' | 'CALL' | 'MAIL';
type Options = { export type SelectType =
[optionName: string]: { | KintoneFormFieldProperty.CheckBox
label: string; | KintoneFormFieldProperty.RadioButton
index: string; | KintoneFormFieldProperty.DropDown
}; | KintoneFormFieldProperty.MultiSelect;
};
export type SelectType = {
type: 'CHECK_BOX' | 'RADIO_BUTTON' | 'DROP_DOWN' | 'MULTI_SELECT';
code: string;
label: string;
options: Options;
};