diff --git a/vue-project/my-kintone-plugin/components.d.ts b/vue-project/my-kintone-plugin/components.d.ts index fb726aa..7455103 100644 --- a/vue-project/my-kintone-plugin/components.d.ts +++ b/vue-project/my-kintone-plugin/components.d.ts @@ -17,5 +17,7 @@ declare module 'vue' { PluginTableArea: typeof import('./src/components/basic/PluginTableArea.vue')['default'] PluginTableConditionRow: typeof import('./src/components/basic/PluginTableConditionRow.vue')['default'] PluginTableConnectRow: typeof import('./src/components/basic/PluginTableConnectRow.vue')['default'] + TableCombobox: typeof import('./src/components/basic/condition/TableCombobox.vue')['default'] + TableInput: typeof import('./src/components/basic/condition/TableInput.vue')['default'] } } diff --git a/vue-project/my-kintone-plugin/env.d.ts b/vue-project/my-kintone-plugin/env.d.ts index 1a06ebe..528bb9b 100644 --- a/vue-project/my-kintone-plugin/env.d.ts +++ b/vue-project/my-kintone-plugin/env.d.ts @@ -1,2 +1,8 @@ /// -/// \ No newline at end of file +/// + +declare module '*.vue' { + import { DefineComponent } from 'vue'; + const component: DefineComponent<{}, {}, any>; + export default component; +} diff --git a/vue-project/my-kintone-plugin/src/components/Config.vue b/vue-project/my-kintone-plugin/src/components/Config.vue index 154ca55..70c1be0 100644 --- a/vue-project/my-kintone-plugin/src/components/Config.vue +++ b/vue-project/my-kintone-plugin/src/components/Config.vue @@ -18,9 +18,9 @@ diff --git a/vue-project/my-kintone-plugin/src/components/basic/PluginTableConnectRow.vue b/vue-project/my-kintone-plugin/src/components/basic/PluginTableConnectRow.vue index 816550d..309294a 100644 --- a/vue-project/my-kintone-plugin/src/components/basic/PluginTableConnectRow.vue +++ b/vue-project/my-kintone-plugin/src/components/basic/PluginTableConnectRow.vue @@ -1,63 +1,63 @@ diff --git a/vue-project/my-kintone-plugin/src/components/basic/condition/TableCombobox.vue b/vue-project/my-kintone-plugin/src/components/basic/condition/TableCombobox.vue new file mode 100644 index 0000000..2d45c66 --- /dev/null +++ b/vue-project/my-kintone-plugin/src/components/basic/condition/TableCombobox.vue @@ -0,0 +1,24 @@ + + + diff --git a/vue-project/my-kintone-plugin/src/components/basic/condition/TableInput.vue b/vue-project/my-kintone-plugin/src/components/basic/condition/TableInput.vue new file mode 100644 index 0000000..3437caf --- /dev/null +++ b/vue-project/my-kintone-plugin/src/components/basic/condition/TableInput.vue @@ -0,0 +1,22 @@ + + + diff --git a/vue-project/my-kintone-plugin/src/js/conditions.ts b/vue-project/my-kintone-plugin/src/js/conditions.ts new file mode 100644 index 0000000..a2e592a --- /dev/null +++ b/vue-project/my-kintone-plugin/src/js/conditions.ts @@ -0,0 +1,38 @@ +import TableCombobox from '@/components/basic/condition/TableCombobox.vue'; +import TableInput from '@/components/basic/condition/TableInput.vue'; + +const component = { + '': undefined, + input: TableInput, + select: TableCombobox, +}; +export type ComponentType = keyof typeof component; + +export type ConditionValue = '' | 'eq' | 'ne'; + +type ConditionItem = { + value: ConditionValue; + label: string; + type: ComponentType; + func: (a: string, b: string) => boolean; +}; + +export const conditionList: ConditionItem[] = [ + { value: '', label: '--------', type: '', func: (a: string, b: string) => true }, + { value: 'eq', label: '=(等しい)', type: 'input', func: (a: string, b: string) => a === b }, + { value: 'ne', label: '≠ (等しくない)', type: 'input', func: (a: string, b: string) => a !== b }, +]; + +// type ConditionItem = (typeof conditionList)[number]; + +export const conditionMap: Record = conditionList.reduce( + (map, item) => { + map[item.value] = item; + return map; + }, + {} as Record, +); + +export const getComponent = (value: ConditionValue) => { + return component[conditionMap[value].type]; +}; diff --git a/vue-project/my-kintone-plugin/src/js/helper.ts b/vue-project/my-kintone-plugin/src/js/helper.ts index 22efbe1..6647644 100644 --- a/vue-project/my-kintone-plugin/src/js/helper.ts +++ b/vue-project/my-kintone-plugin/src/js/helper.ts @@ -1,67 +1,113 @@ -import type { JoinTable } from '@/types/model'; -import type { KucDropdownItem } from '@/types/my-kintone'; -import { client, isType, type App, type Properties, type OneOf } from './kintone-rest-api-client'; +import type { FieldsInfo, JoinTable, WhereCondition } from '@/types/model'; +import { client, isType, type OneOf, type App, type Layout } from './kintone-rest-api-client'; +import type { DropdownItem } from 'kintone-ui-component'; + + +export const EMPTY_OPTION = { + value: '', + label: '--------', +} as DropdownItem; + +export const getEmptyWhereCondition = () => ({ field: '', condition: '', data: '' } as WhereCondition); +export const getEmptyOnCondition = () => ({ leftField: '', rightField: '' }); +export const getEmptyFieldsMapping = () => ({ leftField: '', rightField: '' }); -export const condition = { - unset: '', - eq: '=', -}; export function createEmptyJoinTable(id = Number(new Date())) { - return { - id, - app: '', - table: '', - onConditions: [{ leftField: '', rightField: '' }], - fieldsMapping: [{ leftField: '', rightField: '' }], - whereConditions: [{ field: '', condition: condition.unset, data: '' }], - } as JoinTable; + return resetTable({ id, app: '' } as JoinTable); } export function resetTable(table: JoinTable) { - table.whereConditions = [{ field: '', condition: condition.unset, data: '' }]; - table.onConditions = [{ leftField: '', rightField: '' }]; - table.fieldsMapping = [{ leftField: '', rightField: '' }]; + table.table = ''; + return resetConditions(table); +} + +export function resetConditions(table: JoinTable) { + table.onConditions = [getEmptyOnCondition()]; + table.fieldsMapping = [getEmptyFieldsMapping()]; + table.whereConditions = [getEmptyWhereCondition()]; + return table; } const LIMIT = 100; // 每次请求的最大应用数量 -let allAppsCache: KucDropdownItem[] = []; -let allFieldsCache: Properties = {}; -export const fetchApps = async (offset = 0, _apps: KucDropdownItem[] = []): Promise => { - if (allAppsCache.length) return allAppsCache; +export const loadApps = async (offset = 0, _apps: DropdownItem[] = []): Promise => { const { apps } = await client.app.getApps({ limit: LIMIT, offset }); - const allApps: KucDropdownItem[] = [ + const allApps: DropdownItem[] = [ ..._apps, ...apps.map((app: App) => ({ value: app.appId, label: app.name + '(ID: ' + app.appId + ')' })), ]; if (apps.length === LIMIT) { - return fetchApps(offset + LIMIT, allApps); + return loadApps(offset + LIMIT, allApps); } - allAppsCache = allApps.sort((a, b) => Number(b.value) - Number(a.value)); + allApps.sort((a, b) => Number(b.value) - Number(a.value)); + allApps.unshift(EMPTY_OPTION); return allApps; }; -export const fetchFields = async (appId: string, filter: OneOf['type']) => { - let properties = allFieldsCache; - if (!allFieldsCache.length) { - properties = (await client.app.getFormFields({ app: appId })).properties; - allFieldsCache = properties; - } - const labels = Object.keys(properties).reduce((acc, fieldCode) => { - const field = properties[fieldCode]; - if (filter && !isType[filter](field)) return acc; - acc.push({ - value: fieldCode, - label: field.label + '(FC: ' + fieldCode + ')', - }); - return acc; - }, [] as KucDropdownItem[]); - return labels; +export const loadAppFieldsAndLayout = async (appId: string | number = kintone.app.getId() as number) => { + return { + fields: (await client.app.getFormFields({ app: appId })).properties, + layout: (await client.app.getFormLayout({ app: appId })).layout, + } as FieldsInfo; }; -export const getField = (fieldCode: string) => { - const field = allFieldsCache[fieldCode]; - if (isType.SUBTABLE(field)) { - console.log(field.fields); +export const getFieldsDropdownItems = ( + { fields, layout }: FieldsInfo, + subTableCode?: string, + filterType?: OneOf['type'], +) => { + // get used field codes + let fieldOrder: string[]; + let fieldMap = fields; + if (subTableCode) { + const subTableFields = layout.find((each) => each.type === 'SUBTABLE' && each.code === subTableCode) as any; + fieldOrder = subTableFields?.fields.map((field: { code: string }) => field.code) || []; + fieldMap = fieldMap[subTableCode].fields; + } else { + fieldOrder = extractNoSubTableFields(layout); } - return field; + // create labels + return fieldOrder.reduce( + (acc, fieldCode) => { + const field = fieldMap[fieldCode]; + if (!fieldCode || filterType && !isType[filterType](field)) return acc; + acc.push({ + value: fieldCode, + label: field.label + '(FC: ' + fieldCode + ')', + }); + return acc; + }, + [EMPTY_OPTION], + ); }; + +export const getTableFieldsDropdownItems = ({ fields }: FieldsInfo, filterType?: OneOf['type']) => { + return Object.keys(fields).reduce( + (acc, fieldCode) => { + const field = fields[fieldCode]; + if (filterType && !isType[filterType](field)) return acc; + acc.push({ + value: fieldCode, + label: field.label + '(FC: ' + fieldCode + ')', + }); + return acc; + }, + [EMPTY_OPTION], + ); +}; + +const extractNoSubTableFields = (layout: Layout) => { + return layout.reduce((acc, each) => { + if (each.type === 'SUBTABLE') { + return acc; + } else if (each.type === 'ROW') { + acc.push(...each.fields.map((field: any) => field.code)); + } else if (each.type === 'GROUP') { + acc.push(...extractNoSubTableFields(each.layout)); + } + return acc; + }, [] as string[]); +}; + +// if (isType.SUBTABLE(field)) { +// console.log(field.fields); +// } diff --git a/vue-project/my-kintone-plugin/src/js/kintone-rest-api-client.ts b/vue-project/my-kintone-plugin/src/js/kintone-rest-api-client.ts index 8e11435..cf59117 100644 --- a/vue-project/my-kintone-plugin/src/js/kintone-rest-api-client.ts +++ b/vue-project/my-kintone-plugin/src/js/kintone-rest-api-client.ts @@ -8,6 +8,7 @@ export type App = { }; export type Properties = Awaited>['properties']; +export type Layout = Awaited>['layout']; export type OneOf = Properties[string]; const typeNames = [ diff --git a/vue-project/my-kintone-plugin/src/types/model.d.ts b/vue-project/my-kintone-plugin/src/types/model.d.ts index 035dab3..c5cd67c 100644 --- a/vue-project/my-kintone-plugin/src/types/model.d.ts +++ b/vue-project/my-kintone-plugin/src/types/model.d.ts @@ -1,4 +1,6 @@ -import { condition } from './helper'; +import type { ConditionValue } from '@/js/conditions'; +import type { Layout } from '@/js/kintone-rest-api-client'; +import type { DropdownItem } from 'kintone-ui-component'; export interface FieldsJoinMapping { leftField: string; @@ -7,7 +9,7 @@ export interface FieldsJoinMapping { export interface WhereCondition { field: string; - condition: (typeof condition)[keyof typeof condition]; + condition: ConditionValue; data: string; } @@ -24,4 +26,20 @@ export interface JoinTable { export interface SavedData { buttonName: string; joinTables: JoinTable[]; -} \ No newline at end of file +} + +export interface FieldsInfo { + fields: Properties; + layout: Layout; +} + +export interface CachedData { + apps: DropdownItem[], + currentAppFields: FieldsInfo, +} + +export interface CachedSelectedAppData { + appFields: FieldsInfo, + loading: boolean, + table: JoinTable, +} diff --git a/vue-project/my-kintone-plugin/src/types/my-kintone.d.ts b/vue-project/my-kintone-plugin/src/types/my-kintone.d.ts index 1c0d110..7e32aee 100644 --- a/vue-project/my-kintone-plugin/src/types/my-kintone.d.ts +++ b/vue-project/my-kintone-plugin/src/types/my-kintone.d.ts @@ -1,15 +1,3 @@ -// 组件相关 -export interface KucDropdownItem { - label: string; - value: string; - disabled?: boolean; -} - -export interface KucSpinnerEl { - open: function; - close: function; -} - export interface KucEvent { detail: { value: string; diff --git a/vue-project/my-kintone-plugin/vite.config.ts b/vue-project/my-kintone-plugin/vite.config.ts index 1d70c6e..62e7d82 100644 --- a/vue-project/my-kintone-plugin/vite.config.ts +++ b/vue-project/my-kintone-plugin/vite.config.ts @@ -67,6 +67,7 @@ export default defineConfig({ }, }, build: { + sourcemap: 'inline', rollupOptions: { input: { config: path.resolve(__dirname, 'index.html'),