kintone側実装完了。PVC初回提出版
This commit is contained in:
@@ -75,7 +75,7 @@ function save() {
|
||||
const currentAppMeta = cachedData.currentAppFields.fields;
|
||||
const convertJoinTables = JSON.parse(JSON.stringify(data.joinTables)) as JoinTable<OneOf | string>[];
|
||||
convertJoinTables.forEach((item) => {
|
||||
const meta = getMeta(item.meta as Properties, item.table);
|
||||
const meta = getMeta(item.meta as Properties, item.table,true);
|
||||
|
||||
// Process onConditions
|
||||
item.onConditions.forEach((condition) => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { FieldLayout, FieldsJoinMapping, JoinTable, Record, RecordForParameter, SavedData, WhereCondition } from "@/types/model";
|
||||
import { type OneOf ,isType} from "./field-types";
|
||||
import { type OneOf, isType } from "./field-types";
|
||||
import type { ConditionValue } from "./conditions";
|
||||
declare var KintoneRestAPIClient: typeof import("@kintone/rest-api-client").KintoneRestAPIClient;
|
||||
export class KintoneIndexEventHandler {
|
||||
private config: SavedData<FieldLayout>;
|
||||
@@ -28,27 +29,36 @@ export class KintoneIndexEventHandler {
|
||||
type: "submit",
|
||||
id: 'btn-data-fetch',
|
||||
});
|
||||
|
||||
// const button = document.createElement('button');
|
||||
// button.id = 'btn-data-fetch';
|
||||
// button.textContent = this.config.buttonName;
|
||||
// button.style.margin = '0 8px';
|
||||
button.addEventListener('click', () => this.handleButtonClick());
|
||||
|
||||
headerSpace.appendChild(button);
|
||||
}
|
||||
|
||||
// ボタンクリック
|
||||
private handleButtonClick = async (): Promise<void> => {
|
||||
const spinner = this.showSpinner();
|
||||
try {
|
||||
console.log('データ収集開始...');
|
||||
await this.execDataFectch();
|
||||
spinner.close();
|
||||
location.reload();
|
||||
} catch (error) {
|
||||
console.error('Error during data processing:', error);
|
||||
throw error;
|
||||
spinner.close();
|
||||
const detailError = (error instanceof Error) ? "\n詳細:" + error.message : "";
|
||||
const errorMsg = `データ収集中処理中例外発生しました。${detailError}`;
|
||||
console.error(errorMsg, error);
|
||||
window.alert(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private showSpinner() {
|
||||
const kuc = Kucs['1.18.0'];
|
||||
const spinner = new kuc.Spinner({
|
||||
text: 'データ収集中',
|
||||
container: document.body
|
||||
});
|
||||
spinner.open();
|
||||
return spinner;
|
||||
}
|
||||
|
||||
/**
|
||||
* 検索データ取得&作成処理
|
||||
@@ -68,6 +78,7 @@ export class KintoneIndexEventHandler {
|
||||
for (const table of joinTables) {
|
||||
const subDatas = await this.fetchDataFromApp(table);
|
||||
mainData = this.leftJoin(mainData, subDatas, table);
|
||||
// console.log("LeftJoin", mainData);
|
||||
};
|
||||
//現在のデータをクリアする
|
||||
await this.deleteCurrentRecords();
|
||||
@@ -82,11 +93,17 @@ export class KintoneIndexEventHandler {
|
||||
private fetchDataFromApp = async (joinTable: JoinTable<FieldLayout>): Promise<Record[]> => {
|
||||
// Filter 条件作成
|
||||
const filter = this.getWhereCondition(joinTable.whereConditions);
|
||||
|
||||
//取得列を設定する
|
||||
const fetchFields = joinTable.fieldsMapping.map(map => this.fieldCode(map.leftField));
|
||||
if (joinTable.table) {
|
||||
fetchFields.push(joinTable.table);
|
||||
}
|
||||
const onFields =joinTable.onConditions.map(cond=>this.fieldCode(cond.leftField));
|
||||
onFields.forEach(fld=>{
|
||||
if(!fetchFields.includes(fld)){
|
||||
fetchFields.push(fld);
|
||||
}
|
||||
});
|
||||
// KintoneRESTAPI
|
||||
const client = new KintoneRestAPIClient();
|
||||
const records = await client.record.getAllRecords({
|
||||
@@ -94,24 +111,45 @@ export class KintoneIndexEventHandler {
|
||||
fields: fetchFields,
|
||||
condition: filter
|
||||
});
|
||||
//console.log("Data Fetch", records);
|
||||
//SubTableが含まれる場合、フラットなデータに変換する
|
||||
return this.convertToFlatDatas(records, joinTable.table);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 絞り込み条件式作成
|
||||
* @param whereCondifions
|
||||
* @returns
|
||||
*/
|
||||
private getWhereCondition(whereCondifions: WhereCondition<FieldLayout>[]): string {
|
||||
const conds = whereCondifions
|
||||
.filter((cond) => this.fieldCode(cond.field) !== '');
|
||||
const condition = conds.map((cond) => {
|
||||
const condValue = this.getConditionValue(cond);
|
||||
return `${this.fieldCode(cond.field)} ${cond.condition} ${condValue}`;
|
||||
let condition = cond.condition;
|
||||
if ("subField" in cond.field && cond.field.subField) {
|
||||
condition = this.mapConditionForSubField(cond.condition);
|
||||
}
|
||||
const condValue = this.getConditionValue(cond.field as OneOf, condition, cond.data);
|
||||
return `${this.fieldCode(cond.field)} ${condition} ${condValue}`;
|
||||
}).join(' and ');
|
||||
return condition;
|
||||
}
|
||||
|
||||
private getConditionValue(condi: WhereCondition<FieldLayout>): string {
|
||||
const field = condi.field as OneOf;
|
||||
const data = condi.data;
|
||||
/**
|
||||
* サブフィールドの演算子対応
|
||||
* @param condition
|
||||
* @returns
|
||||
*/
|
||||
private mapConditionForSubField(condition: ConditionValue): ConditionValue {
|
||||
switch (condition) {
|
||||
case "=":
|
||||
return "in";
|
||||
case "!=":
|
||||
return "not in";
|
||||
default:
|
||||
return condition; // 既存の条件をそのまま使用
|
||||
}
|
||||
}
|
||||
private getConditionValue(field: OneOf, condition: ConditionValue, data: string): string {
|
||||
if (!data) return "";
|
||||
if (isType.NUMBER(field) || isType.RECORD_NUMBER(field)) {
|
||||
// For numbers, return as is
|
||||
@@ -130,13 +168,13 @@ export class KintoneIndexEventHandler {
|
||||
}
|
||||
const dateTime = new Date(data);
|
||||
return `"${dateTime.toISOString()}"`;
|
||||
} else if ((condi.condition === "in" || condi.condition === "not in" )) {
|
||||
if( data.includes(",")){
|
||||
} else if ((condition === "in" || condition === "not in")) {
|
||||
if (data.includes(",")) {
|
||||
// Handle "in" and "not in" with comma-separated strings
|
||||
const items = data.split(",").map(item => `"${item.trim()}"`);
|
||||
return `(${items.join(",")})`;
|
||||
} else {
|
||||
return `"${data}"`;
|
||||
return `("${data}")`;
|
||||
}
|
||||
} else {
|
||||
// Default case for other types (treat as text)
|
||||
@@ -182,7 +220,7 @@ export class KintoneIndexEventHandler {
|
||||
|
||||
// サブテーブルフィールドを抽出してフラットな構造に追加
|
||||
Object.entries(nested.value).forEach(([key, field]) => {
|
||||
flatRecord[key] = field.value;
|
||||
flatRecord[key] = { value: field.value, type: field.type };
|
||||
});
|
||||
|
||||
// テーブルフィールドを削除
|
||||
@@ -198,7 +236,7 @@ export class KintoneIndexEventHandler {
|
||||
flattenedData.push(flatRecord);
|
||||
}
|
||||
});
|
||||
|
||||
// console.log("FlatDatas=>", flattenedData);
|
||||
return flattenedData;
|
||||
}
|
||||
|
||||
@@ -215,58 +253,31 @@ export class KintoneIndexEventHandler {
|
||||
subData: Record[],
|
||||
joinTable: JoinTable<FieldLayout>
|
||||
): Record[] {
|
||||
|
||||
const joinedRecords = mainData.map((mainRecord) => {
|
||||
const matchedRecord = subData.find((subRecord) =>
|
||||
const joinedRecords: Record[] = [];
|
||||
mainData.forEach((mainRecord) => {
|
||||
const matchedRecords = subData.filter((subRecord) =>
|
||||
joinTable.onConditions.every(
|
||||
(cond) => mainRecord[this.fieldCode(cond.leftField)] === subRecord[this.fieldCode(cond.rightField)]
|
||||
(cond) => mainRecord[this.fieldCode(cond.rightField)]?.value === subRecord[this.fieldCode(cond.leftField)]?.value
|
||||
)
|
||||
);
|
||||
|
||||
// マッチ出来ない場合、LEFTの列のみ返す
|
||||
if (!matchedRecord) return mainRecord;
|
||||
|
||||
// フィールド結合
|
||||
const combinedRecord: Record = { ...mainRecord };
|
||||
joinTable.fieldsMapping.forEach((mapping) => {
|
||||
combinedRecord[this.fieldCode(mapping.rightField)] = matchedRecord[this.fieldCode(mapping.leftField)];
|
||||
});
|
||||
return combinedRecord;
|
||||
if (!matchedRecords) {
|
||||
joinedRecords.push(mainRecord);
|
||||
} else {
|
||||
matchedRecords.forEach((matchedRecord) => {
|
||||
// フィールド結合
|
||||
const combinedRecord: Record = { ...mainRecord };
|
||||
joinTable.fieldsMapping.forEach((mapping) => {
|
||||
combinedRecord[this.fieldCode(mapping.rightField)] = matchedRecord[this.fieldCode(mapping.leftField)];
|
||||
});
|
||||
joinedRecords.push(combinedRecord);
|
||||
});
|
||||
}
|
||||
});
|
||||
return joinedRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得先はテーブルの場合の特別対応
|
||||
*/
|
||||
private leftJoinForTable(
|
||||
mainData: Record[],
|
||||
subData: Record[],
|
||||
joinTable: JoinTable
|
||||
): any[] {
|
||||
return mainData.map((mainRecord) => {
|
||||
const matchedRecord = subData.find((subRecord) => {
|
||||
const subRows = subRecord[joinTable.table].value as Record[];
|
||||
joinTable.onConditions.every(
|
||||
(cond) => mainRecord[cond.leftField] === subRecord[cond.rightField]
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
// マッチ出来ない場合、LEFTの列のみ返す
|
||||
if (!matchedRecord) return mainRecord;
|
||||
|
||||
// フィールド結合
|
||||
const combinedRecord = { ...mainRecord };
|
||||
joinTable.fieldsMapping.forEach((mapping) => {
|
||||
combinedRecord[mapping.rightField] = matchedRecord[mapping.leftField];
|
||||
});
|
||||
return combinedRecord;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 現在アプリのすべてレコードを削除する
|
||||
*/
|
||||
|
||||
@@ -3,12 +3,18 @@ import { KintoneIndexEventHandler } from "./KintoneIndexEventHandler";
|
||||
|
||||
(function (PLUGIN_ID) {
|
||||
kintone.events.on('app.record.index.show', (event) => {
|
||||
const setting = kintone.plugin.app.getConfig(PLUGIN_ID);
|
||||
const config:SavedData<FieldLayout> = getConfig(setting);
|
||||
const currentApp = kintone.app.getId()?.toString();
|
||||
if(!currentApp) return;
|
||||
const handler = new KintoneIndexEventHandler(config,currentApp);
|
||||
handler.init();
|
||||
try{
|
||||
const setting = kintone.plugin.app.getConfig(PLUGIN_ID);
|
||||
const config:SavedData<FieldLayout> = getConfig(setting);
|
||||
const currentApp = kintone.app.getId()?.toString();
|
||||
if(!currentApp) return;
|
||||
const handler = new KintoneIndexEventHandler(config,currentApp);
|
||||
handler.init();
|
||||
}catch(error){
|
||||
const detailError =(error instanceof Error) ? "\n詳細:" + error.message : "";
|
||||
const errorMsg = `データ収集中処理中例外発生しました。${ detailError }`;
|
||||
event.error = errorMsg;
|
||||
}
|
||||
return event;
|
||||
});
|
||||
/**
|
||||
@@ -24,244 +30,5 @@ import { KintoneIndexEventHandler } from "./KintoneIndexEventHandler";
|
||||
return config;
|
||||
}
|
||||
|
||||
// function getTestSetting(config:SavedData):SavedData{
|
||||
// const retConfig :SavedData<FieldLayout> ={
|
||||
// "buttonName": "集約する",
|
||||
// "joinTables": [
|
||||
// {
|
||||
// "id": "m6c69ojr-bx9l8n9fm",
|
||||
// "app": "140",
|
||||
// "table": "",
|
||||
// "onConditions": [
|
||||
// {
|
||||
// "leftField": "",
|
||||
// "rightField": "",
|
||||
// "id": "m6c69ojr-7pho6voer"
|
||||
// }
|
||||
// ],
|
||||
// "fieldsMapping": [
|
||||
// {
|
||||
// "leftField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行_",
|
||||
// "label": "社員番号",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "rightField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行_",
|
||||
// "label": "社員番号",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "id": "m6c69ojr-i75a82qvb"
|
||||
// },
|
||||
// {
|
||||
// "leftField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行__0",
|
||||
// "label": "氏名",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "rightField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行__0",
|
||||
// "label": "氏名",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "id": "m6c6v8sp-7yw58m6e9"
|
||||
// }
|
||||
// ],
|
||||
// "whereConditions": [
|
||||
// {
|
||||
// "field": "",
|
||||
// "condition": "",
|
||||
// "data": "",
|
||||
// "id": "m6c69ojr-az5k7bvp6"
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// "id": "m6c6u15u-yq4kzp31c",
|
||||
// "app": "141",
|
||||
// "table": "使用者テーブル",
|
||||
// "onConditions": [
|
||||
// {
|
||||
// "leftField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "社員番号",
|
||||
// "label": "社員番号",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "rightField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行_",
|
||||
// "label": "社員番号",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "id": "m6c6ue5e-k7yibisue"
|
||||
// }
|
||||
// ],
|
||||
// "fieldsMapping": [
|
||||
// {
|
||||
// "leftField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "氏名",
|
||||
// "label": "氏名",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "rightField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行__0",
|
||||
// "label": "氏名",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "id": "m6c6ue5e-bjdpae18q"
|
||||
// }
|
||||
// ],
|
||||
// "whereConditions": [
|
||||
// {
|
||||
// "field": "",
|
||||
// "condition": "",
|
||||
// "data": "",
|
||||
// "id": "m6c6ue5e-1rf2v4l9m"
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// "id": "m6c6vrso-vr7a7v5h1",
|
||||
// "app": "143",
|
||||
// "table": "テーブル",
|
||||
// "onConditions": [
|
||||
// {
|
||||
// "leftField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行__1",
|
||||
// "label": "資産管理番号",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "rightField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行__1",
|
||||
// "label": "資産管理番号",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "id": "m6c6vx94-02xbd48xt"
|
||||
// }
|
||||
// ],
|
||||
// "fieldsMapping": [
|
||||
// {
|
||||
// "leftField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行__2",
|
||||
// "label": "資産名",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "rightField": {
|
||||
// "type": "SINGLE_LINE_TEXT",
|
||||
// "code": "文字列__1行__2",
|
||||
// "label": "資産名",
|
||||
// "noLabel": false,
|
||||
// "required": false,
|
||||
// "minLength": "",
|
||||
// "maxLength": "",
|
||||
// "expression": "",
|
||||
// "hideExpression": false,
|
||||
// "unique": false,
|
||||
// "defaultValue": ""
|
||||
// },
|
||||
// "id": "m6c6vx94-t7d8juf6x"
|
||||
// }
|
||||
// ],
|
||||
// "whereConditions": [
|
||||
// {
|
||||
// "field": "",
|
||||
// "condition": "",
|
||||
// "data": "",
|
||||
// "id": "m6c6vx94-gbxhjgf8m"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// };
|
||||
// return retConfig;
|
||||
// }
|
||||
|
||||
})(kintone.$PLUGIN_ID);
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ function flatFields(fields: Properties) {
|
||||
const copy = JSON.parse(JSON.stringify(subField)) as typeof subField;
|
||||
copy.label = '[' + field.code + '].' + subField.label;
|
||||
subtableFields[subField.code] = copy;
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
return { ...fields, ...subtableFields };
|
||||
@@ -191,14 +191,24 @@ export function getFieldObj(fieldCode: string, { fields }: FieldsInfo, subTableC
|
||||
return meta[fieldCode];
|
||||
}
|
||||
|
||||
export function getMeta(fields: Properties, subTableCode?: string) {
|
||||
export function getMeta(fields: Properties, subTableCode?: string ,allField?:boolean) {
|
||||
if (!fields || !subTableCode) {
|
||||
return fields;
|
||||
}
|
||||
let meta = fields;
|
||||
const table = meta[subTableCode];
|
||||
if (isType.SUBTABLE(table)) {
|
||||
meta = table.fields;
|
||||
const subFields = table.fields; ;
|
||||
Object.values(subFields).forEach(field=>{
|
||||
if (typeof field === 'object' && field !== null) {
|
||||
(field as Record<string, any>).subField = true;
|
||||
}
|
||||
});
|
||||
if(allField){
|
||||
meta={ ...fields, ...subFields };
|
||||
}else{
|
||||
meta=subFields;
|
||||
}
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
@@ -80,6 +80,6 @@ export default defineConfig({
|
||||
assetFileNames: 'src/[ext]/[name].[ext]',
|
||||
},
|
||||
},
|
||||
sourcemap:'inline',
|
||||
sourcemap:false,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user