import { Record } from "@kintone/rest-api-client/lib/src/client/types"; import { actionAddins } from "."; import { IAction,IActionResult, IActionNode, IActionProperty, IField, IContext } from "../types/ActionTypes"; import { ConditionTree } from '../types/Conditions'; type TextStyle = "太字" | "斜体" | "下線" | "打ち消し線"; type StyleRigion = "書式変更フィールド" | "行全体"|""; /** * アクションの属性定義 */ interface IStyleFieldProps{ field:IField; fontColor:string; bgColor:string; fontStyle:TextStyle[]; allRow:StyleRigion; condition:string; } /** * 条件書式表示アクション */ export class StyleFieldAction implements IAction{ name: string; actionProps: IActionProperty[]; props:IStyleFieldProps; constructor(){ this.name="条件書式表示"; this.actionProps=[]; this.props={ field:{code:''}, fontColor:'', bgColor:'', fontStyle:[], allRow:'', condition:'' } //アクションを登録する this.register(); } /** * アクションの実行を呼び出す * @param actionNode * @param event * @returns */ async process(actionNode:IActionNode,event:any,context:IContext):Promise { let result={ canNext:true, result:false }; try{ //属性設定を取得する this.actionProps=actionNode.actionProps; if (!('field' in actionNode.ActionValue) && !('allRow' in actionNode.ActionValue)) { return result } this.props = actionNode.ActionValue as IStyleFieldProps; //書式設定 if(event.type==="app.record.index.show"){ this.setStyleForView(event,this.props,context); }else if(event.type==="app.record.detail.show"){ this.setStyleForDetail(event,this.props,context); } result= { canNext:true, result:true } return result; }catch(error){ context.errors.handleError(error,actionNode); result.canNext=false; return result; } } /** * 詳細表示時のスタイル設定 * @param event * @param props * @param context * @returns */ setStyleForDetail(event:any,props:IStyleFieldProps,context:IContext){ const elem = kintone.app.record.getFieldElement(props.field.code); if(!elem){ return; } const tree = this.getCondition(props.condition); const conditionResult = this.getConditionResult(tree,context); if(conditionResult){ this.setFieldStyle(props,elem); } } /** * 一覧表示時の書式設定 * @param event * @param props * @param context * @returns */ setStyleForView(event:any,props:IStyleFieldProps,context:IContext){ const records:Record[] = event.records; const cells = kintone.app.getFieldElements(props.field.code); if(!cells){ return; } let elem :HTMLElement|null; const conditionTree = this.getCondition(props.condition); records.forEach((record:Record,index:number) => { const currContext:IContext = { variables:context.variables, record:record, errors:context.errors } const conditionResult = this.getConditionResult(conditionTree,currContext); if(conditionResult){ elem = cells[index]; if(props.allRow==="行全体"){ elem = cells[index].parentElement; } if(elem){ this.setFieldStyle(props,elem); } } }); } /** * * @param props HtmlElement書式設定 */ setFieldStyle(props:IStyleFieldProps,elem:HTMLElement){ if(props.fontColor){ elem.style.color=props.fontColor; } if(props.bgColor){ elem.style.backgroundColor=props.bgColor; } if(props.fontStyle.length>0){ if(props.fontStyle.includes("斜体")){ elem.style.fontStyle="italic"; } if(props.fontStyle.includes("太字")){ elem.style.fontWeight = "bold"; } let textDecoration=""; if(props.fontStyle.includes("下線")){ textDecoration="underline"; } if(props.fontStyle.includes("打ち消し線")){ textDecoration = textDecoration? textDecoration + " line-through":"line-through"; } if(textDecoration){ elem.style.textDecoration=textDecoration; } } } /** * 条件式を実行する * @param tree 条件式オブジェクト * @param context * @returns */ getConditionResult(tree:ConditionTree|null, context:any):boolean{ if(!tree){ //条件を設定されていません return true; } return tree.evaluate(tree.root,context); } /** * @param condition 条件式ツリーを取得する * @returns */ getCondition(condition:string):ConditionTree|null{ try{ const tree = new ConditionTree(); tree.fromJson(condition); if(tree.getConditions(tree.root).length>0){ return tree; }else{ return null; } }catch(error){ return null; } } register(): void { actionAddins[this.name]=this; } } new StyleFieldAction();