272 lines
7.4 KiB
TypeScript
272 lines
7.4 KiB
TypeScript
import {
|
|
IAction,
|
|
IActionResult,
|
|
IActionNode,
|
|
IActionProperty,
|
|
IContext,
|
|
IField,
|
|
} from "../types/ActionTypes";
|
|
|
|
import { actionAddins } from ".";
|
|
import type { Record} from "@kintone/rest-api-client/lib/src/client/types";
|
|
import { KintoneRestAPIClient} from "@kintone/rest-api-client";
|
|
import "./auto-lookup.scss";
|
|
import "bootstrap/js/dist/modal";
|
|
// import "bootstrap/js/dist/spinner";
|
|
import {Modal} from "bootstrap"
|
|
import $ from "jquery";
|
|
|
|
interface Props {
|
|
displayName: string;
|
|
lookupField: LookupField;
|
|
condition: Condition;
|
|
}
|
|
|
|
interface Condition {
|
|
queryString: string;
|
|
index: number;
|
|
type: string;
|
|
children: Child[];
|
|
parent: null;
|
|
logicalOperator: string;
|
|
}
|
|
|
|
interface Child {
|
|
index: number;
|
|
type: string;
|
|
parent: string;
|
|
object: any;
|
|
operator: string;
|
|
value: string;
|
|
}
|
|
|
|
interface LookupField {
|
|
app: App;
|
|
fields: Field[];
|
|
}
|
|
|
|
interface Field {
|
|
name: string;
|
|
type: string;
|
|
code: string;
|
|
label: string;
|
|
noLabel: boolean;
|
|
required: boolean;
|
|
lookup: Lookup;
|
|
}
|
|
|
|
interface Lookup {
|
|
relatedApp: RelatedApp;
|
|
relatedKeyField: string;
|
|
fieldMappings: FieldMapping[];
|
|
lookupPickerFields: any[];
|
|
filterCond: string;
|
|
sort: string;
|
|
}
|
|
|
|
interface FieldMapping {
|
|
field: string;
|
|
relatedField: string;
|
|
}
|
|
|
|
interface RelatedApp {
|
|
app: string;
|
|
code: string;
|
|
}
|
|
|
|
interface App {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
createdate: string;
|
|
}
|
|
|
|
export class AutoLookUpAction implements IAction {
|
|
name: string;
|
|
actionProps: IActionProperty[];
|
|
props: Props;
|
|
constructor() {
|
|
this.name = "ルックアップ更新";
|
|
this.actionProps = [];
|
|
this.props = {} as Props;
|
|
this.register();
|
|
}
|
|
|
|
/***
|
|
* アクセスのメインの処理関数
|
|
*/
|
|
async process(
|
|
prop: IActionNode,
|
|
event: any,
|
|
context: IContext
|
|
): Promise<IActionResult> {
|
|
this.actionProps = prop.actionProps;
|
|
this.props = {
|
|
...prop.ActionValue,
|
|
condition: JSON.parse((prop.ActionValue as any).condition),
|
|
} as Props;
|
|
// console.log(context);
|
|
|
|
let result = {
|
|
canNext: true,
|
|
result: "",
|
|
} as IActionResult;
|
|
try {
|
|
const lookUpFields = this.props.lookupField.fields.filter(
|
|
(f) => f.lookup && f.lookup.relatedApp.app === String(kintone.app.getId())
|
|
);
|
|
if (!lookUpFields || lookUpFields.length===0) {
|
|
throw new Error(
|
|
`ルックアップの設定は不正です。${this.props.lookupField.fields[0].label} `
|
|
);
|
|
}
|
|
const lookUpField = this.props.lookupField.fields[0];
|
|
const key = event.record[lookUpField.lookup.relatedKeyField].value;
|
|
const targetRecords = await this.getUpdateRecords(lookUpField, key);
|
|
//更新対象がない時にスキップ
|
|
if(targetRecords.length===0){
|
|
return result;
|
|
}
|
|
const updateRecords = this.convertForLookup(targetRecords,lookUpField,key);
|
|
console.log("updateRecords", updateRecords);
|
|
this.showSpinnerModel(this.props.lookupField.app);
|
|
await this.updateLookupTarget(updateRecords);
|
|
this.showResult(this.props.lookupField.app,updateRecords.length);
|
|
} catch (error) {
|
|
console.error("ルックアップ更新中例外が発生しました。", error);
|
|
if(error instanceof Error){
|
|
event.error = error.message;
|
|
}else{
|
|
event.error = "ルックアップ更新中例外が発生しました。";
|
|
}
|
|
result.canNext = false;
|
|
}
|
|
console.log("autoLookupProps", this.props);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* REST API用クエリ作成
|
|
* TODO:共通関数として作成
|
|
* @param lookUpField
|
|
* @param key
|
|
* @returns
|
|
*/
|
|
makeQuery=(lookUpField:Field,key:any)=>{
|
|
if(typeof key==='number'){
|
|
return `${lookUpField.code} = ${key}`
|
|
}
|
|
if(typeof key==='string'){
|
|
return `${lookUpField.code} = "${key}"`
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新対象のレコードを取得する
|
|
*/
|
|
getUpdateRecords = async (lookUpField:Field,key:any):Promise< Record[]>=>{
|
|
const client=new KintoneRestAPIClient();
|
|
const resp = await client.record.getAllRecords({
|
|
app:this.props.lookupField.app.id,
|
|
fields:["$id"],
|
|
condition:this.makeQuery(lookUpField,key)
|
|
});
|
|
return resp;
|
|
}
|
|
|
|
/**
|
|
* ルックアップ更新用レコードに変換する
|
|
* @param targetRecords 更新対象レコード
|
|
* @param lookUpField ルックアップフィールド
|
|
* @param key ルックアップフィールドの値
|
|
* @returns
|
|
*/
|
|
convertForLookup = (targetRecords:Record[],lookUpField:Field,key:any):Array<any>=>{
|
|
return targetRecords.map((r) => ({
|
|
id: Number(r["$id"].value),
|
|
record: { [lookUpField.code]: { value: key } },
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* ルックアップ先を更新する
|
|
* @param updateRecords
|
|
*/
|
|
updateLookupTarget = async (updateRecords:Array<any>)=>{
|
|
if (updateRecords && updateRecords.length > 0) {
|
|
const client=new KintoneRestAPIClient();
|
|
client.record.updateAllRecords({
|
|
app:this.props.lookupField.app.id,
|
|
records:updateRecords
|
|
});
|
|
// await kintone.api(kintone.api.url("/k/v1/records.json", true), "PUT", {
|
|
// app: this.props.lookupField.app.id,
|
|
// records: updateRecords
|
|
// });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新中のダイアログ表示
|
|
* @param app
|
|
*/
|
|
showSpinnerModel = (app:App) => {
|
|
let dialog = $("#alcLookupModal");
|
|
if(dialog.length===0){
|
|
const modalHTML = `
|
|
<div class="modal" id="alcLookupModal" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
|
<div class="modal-dialog-centered">
|
|
<div class="modal-dialog modal-content">
|
|
<div class="modal-header">
|
|
<h1 class="modal-title fs-5" id="alcLookupModalLabel">ルックアップ同期処理</h1>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row" id="app${app.id}">
|
|
<div class="spinner-border text-secondary col-1 " role="alert"></div>
|
|
<div class="col">${app.name}</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>`;
|
|
dialog = $(modalHTML).appendTo("body");
|
|
dialog.get()[0].addEventListener('hidden.bs.modal',(ev)=>{
|
|
Modal.getOrCreateInstance(dialog.get()[0]).dispose();
|
|
$("#alcLookupModal").remove();
|
|
});
|
|
}else{
|
|
const dialogBody=$("#alcLookupModal .modal-body");
|
|
const htmlrow=`
|
|
<div class="row" id="app${app.id}">
|
|
<div class="spinner-border text-secondary col-1 " role="alert">
|
|
</div>
|
|
<div class="col">${app.name}</div>
|
|
<div>`;
|
|
dialogBody.append(htmlrow);
|
|
}
|
|
Modal.getOrCreateInstance(dialog.get()[0]).show();
|
|
}
|
|
|
|
/**
|
|
* 更新結果を表示する
|
|
* @param app 更新先アプリ情報
|
|
* @param count 更新件数
|
|
*/
|
|
showResult=(app:App,count:number)=>{
|
|
const dialogBody=$(`#alcLookupModal .modal-body #app${app.id}`);
|
|
const html=` <div class="col-1 text-success">✔</div>
|
|
<div class="col">${app.name}</div>
|
|
<div class="col">更新件数:${count}件</div>`;
|
|
dialogBody.html(html);
|
|
}
|
|
|
|
register(): void {
|
|
actionAddins[this.name] = this;
|
|
}
|
|
}
|
|
|
|
new AutoLookUpAction(); |