データ収集プラグインの追加
This commit is contained in:
@@ -203,10 +203,10 @@ export default defineComponent({
|
|||||||
"operator": "COUNT",
|
"operator": "COUNT",
|
||||||
"label": "カウント"
|
"label": "カウント"
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
"operator": "FIRST",
|
// "operator": "FIRST",
|
||||||
"label": "最初の値"
|
// "label": "最初の値"
|
||||||
}
|
// }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
|
|||||||
274
plugin/kintone-addins/src/actions/data-processing.ts
Normal file
274
plugin/kintone-addins/src/actions/data-processing.ts
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
import {
|
||||||
|
IAction,
|
||||||
|
IActionResult,
|
||||||
|
IActionNode,
|
||||||
|
IActionProperty,
|
||||||
|
IContext,
|
||||||
|
} from "../types/ActionTypes";
|
||||||
|
import { actionAddins } from ".";
|
||||||
|
|
||||||
|
type DataProcessingProps = {
|
||||||
|
app: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
conditionsQuery: string;
|
||||||
|
propcessing: {
|
||||||
|
varRootName: string;
|
||||||
|
fields: Field[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type Field = {
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
type: string;
|
||||||
|
varName: string;
|
||||||
|
operator: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class DataProcessingAction implements IAction {
|
||||||
|
name: string;
|
||||||
|
actionProps: IActionProperty[];
|
||||||
|
dataProcessingProps: DataProcessingProps | null;
|
||||||
|
constructor() {
|
||||||
|
this.name = "データ処理";
|
||||||
|
this.actionProps = [];
|
||||||
|
this.dataProcessingProps = null;
|
||||||
|
this.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
async process(
|
||||||
|
nodes: IActionNode,
|
||||||
|
event: any,
|
||||||
|
context: IContext
|
||||||
|
): Promise<IActionResult> {
|
||||||
|
this.initActionProps(nodes);
|
||||||
|
this.initTypedActionProps();
|
||||||
|
let result = {
|
||||||
|
canNext: true,
|
||||||
|
result: "",
|
||||||
|
} as IActionResult;
|
||||||
|
try {
|
||||||
|
if (!this.dataProcessingProps) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await selectData(this.dataProcessingProps.conditionsQuery);
|
||||||
|
console.log("data ", data);
|
||||||
|
|
||||||
|
context.variables[this.dataProcessingProps.propcessing.varRootName] =
|
||||||
|
this.dataProcessingProps.propcessing.fields.reduce((acc, f) => {
|
||||||
|
const v = calc(f, data);
|
||||||
|
if (v) {
|
||||||
|
acc[f.varName] = calc(f, data);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {} as Var);
|
||||||
|
|
||||||
|
console.log("context ", context);
|
||||||
|
return result;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register(): void {
|
||||||
|
actionAddins[this.name] = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private initActionProps(nodes: IActionNode) {
|
||||||
|
this.actionProps = nodes.actionProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
private initTypedActionProps() {
|
||||||
|
this.dataProcessingProps = {
|
||||||
|
app: {
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
conditionsQuery: "",
|
||||||
|
propcessing: {
|
||||||
|
varRootName: "",
|
||||||
|
fields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
for (const action of this.actionProps) {
|
||||||
|
if (action.component === "AppFieldSelect") {
|
||||||
|
this.dataProcessingProps.app.id = action.props.modelValue.app.id;
|
||||||
|
this.dataProcessingProps.app.name = action.props.modelValue.app.name;
|
||||||
|
} else if (action.component === "DataProcessing") {
|
||||||
|
this.dataProcessingProps.propcessing.varRootName =
|
||||||
|
action.props.modelValue.name;
|
||||||
|
for (const f of action.props.modelValue.vars) {
|
||||||
|
this.dataProcessingProps.propcessing.fields.push({
|
||||||
|
name: f.field.name,
|
||||||
|
code: f.field.code,
|
||||||
|
type: f.field.type,
|
||||||
|
varName: f.vName,
|
||||||
|
operator: f.logicalOperator.operator,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (action.component === "ConditionInput") {
|
||||||
|
this.dataProcessingProps.conditionsQuery = JSON.parse(
|
||||||
|
action.props.modelValue
|
||||||
|
).queryString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new DataProcessingAction();
|
||||||
|
|
||||||
|
const selectData = async (query?: string) => {
|
||||||
|
return kintone
|
||||||
|
.api(kintone.api.url("/k/v1/records", true), "GET", {
|
||||||
|
app: kintone.app.getId(),
|
||||||
|
query: query,
|
||||||
|
})
|
||||||
|
.then((resp: Resp) => {
|
||||||
|
const result: Result = {};
|
||||||
|
resp.records.forEach((element) => {
|
||||||
|
for (const [key, value] of Object.entries(element)) {
|
||||||
|
if (!result[key]) {
|
||||||
|
result[key] = { type: value.type, value: [] };
|
||||||
|
}
|
||||||
|
result[key].value.push(value.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
type Resp = { records: RespRecordType[] };
|
||||||
|
|
||||||
|
type RespRecordType = {
|
||||||
|
[key: string]: {
|
||||||
|
type: string;
|
||||||
|
value: any;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type Result = {
|
||||||
|
[key: string]: {
|
||||||
|
type: string;
|
||||||
|
value: any[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type Var = {
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ERROR_TYPE = "ERROR_TYPE";
|
||||||
|
|
||||||
|
const calc = (field: Field, result: Result) => {
|
||||||
|
const type = typeCheck(field.type);
|
||||||
|
if (!type) {
|
||||||
|
return ERROR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fun =
|
||||||
|
calcFunc[`${type}_${Operator[field.operator as keyof typeof Operator]}`];
|
||||||
|
if (!fun) {
|
||||||
|
return ERROR_TYPE;
|
||||||
|
}
|
||||||
|
const values = result[field.code].value;
|
||||||
|
if (!values) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return fun(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const typeCheck = (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case "RECORD_NUMBER":
|
||||||
|
case "NUMBER":
|
||||||
|
return CalcType.NUMBER;
|
||||||
|
case "SINGLE_LINE_TEXT":
|
||||||
|
case "MULTI_LINE_TEXT":
|
||||||
|
case "RICH_TEXT":
|
||||||
|
return CalcType.STRING;
|
||||||
|
case "UPDATED_TIME":
|
||||||
|
case "DATE":
|
||||||
|
case "TIME":
|
||||||
|
case "DATETIME":
|
||||||
|
return CalcType.DATE;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Operator {
|
||||||
|
SUM = "SUM",
|
||||||
|
AVG = "AVG",
|
||||||
|
MAX = "MAX",
|
||||||
|
MIN = "MIN",
|
||||||
|
COUNT = "COUNT",
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CalcType {
|
||||||
|
NUMBER = "number",
|
||||||
|
STRING = "string",
|
||||||
|
DATE = "date",
|
||||||
|
TIME = "time",
|
||||||
|
DATETIME = "datetime",
|
||||||
|
}
|
||||||
|
|
||||||
|
const calcFunc: Record<string, (value: string[]) => string | null> = {
|
||||||
|
[`${CalcType.NUMBER}_${Operator.COUNT}`]: (value: string[]) =>
|
||||||
|
value.length.toString(),
|
||||||
|
[`${CalcType.STRING}_${Operator.COUNT}`]: (value: string[]) =>
|
||||||
|
value.length.toString(),
|
||||||
|
[`${CalcType.DATE}_${Operator.COUNT}`]: (value: string[]) =>
|
||||||
|
value.length.toString(),
|
||||||
|
[`${CalcType.TIME}_${Operator.COUNT}`]: (value: string[]) =>
|
||||||
|
value.length.toString(),
|
||||||
|
[`${CalcType.DATETIME}_${Operator.COUNT}`]: (value: string[]) =>
|
||||||
|
value.length.toString(),
|
||||||
|
|
||||||
|
[`${CalcType.NUMBER}_${Operator.SUM}`]: (value: string[]) =>
|
||||||
|
value.reduce((acc, v) => acc + Number(v), 0).toString(),
|
||||||
|
[`${CalcType.NUMBER}_${Operator.AVG}`]: (value: string[]) =>
|
||||||
|
(value.reduce((acc, v) => acc + Number(v), 0) / value.length).toString(),
|
||||||
|
[`${CalcType.NUMBER}_${Operator.MAX}`]: (value: string[]) =>
|
||||||
|
Math.max(...value.map(Number)).toString(),
|
||||||
|
[`${CalcType.NUMBER}_${Operator.MIN}`]: (value: string[]) =>
|
||||||
|
Math.min(...value.map(Number)).toString(),
|
||||||
|
|
||||||
|
[`${CalcType.STRING}_${Operator.SUM}`]: (value: string[]) => value.join(" "),
|
||||||
|
|
||||||
|
[`${CalcType.DATE}_${Operator.MAX}`]: (value: string[]) =>
|
||||||
|
value.reduce((maxDate, currentDate) =>
|
||||||
|
maxDate > currentDate ? maxDate : currentDate
|
||||||
|
),
|
||||||
|
|
||||||
|
[`${CalcType.DATE}_${Operator.MIN}`]: (value: string[]) =>
|
||||||
|
value.reduce((minDate, currentDate) =>
|
||||||
|
minDate < currentDate ? minDate : currentDate
|
||||||
|
),
|
||||||
|
|
||||||
|
[`${CalcType.TIME}_${Operator.MAX}`]: (value: string[]) =>
|
||||||
|
value.reduce((maxTime, currentTime) =>
|
||||||
|
maxTime > currentTime ? maxTime : currentTime
|
||||||
|
),
|
||||||
|
[`${CalcType.TIME}_${Operator.MIN}`]: (value: string[]) =>
|
||||||
|
value.reduce((minTime, currentTime) =>
|
||||||
|
minTime < currentTime ? minTime : currentTime
|
||||||
|
),
|
||||||
|
|
||||||
|
[`${CalcType.DATETIME}_${Operator.MAX}`]: (value: string[]) =>
|
||||||
|
value.reduce((maxDateTime, currentDateTime) =>
|
||||||
|
new Date(maxDateTime) > new Date(currentDateTime)
|
||||||
|
? maxDateTime
|
||||||
|
: currentDateTime
|
||||||
|
),
|
||||||
|
|
||||||
|
[`${CalcType.DATETIME}_${Operator.MIN}`]: (value: string[]) =>
|
||||||
|
value.reduce((minDateTime, currentDateTime) =>
|
||||||
|
new Date(minDateTime) < new Date(currentDateTime)
|
||||||
|
? minDateTime
|
||||||
|
: currentDateTime
|
||||||
|
),
|
||||||
|
};
|
||||||
@@ -6,6 +6,7 @@ import '../actions/field-shown';
|
|||||||
import '../actions/error-show';
|
import '../actions/error-show';
|
||||||
import '../actions/button-add';
|
import '../actions/button-add';
|
||||||
import '../actions/condition-action';
|
import '../actions/condition-action';
|
||||||
|
import '../actions/data-processing';
|
||||||
import { ActionFlow,IActionFlow, IActionResult,IContext } from "./ActionTypes";
|
import { ActionFlow,IActionFlow, IActionResult,IContext } from "./ActionTypes";
|
||||||
|
|
||||||
export class ActionProcess{
|
export class ActionProcess{
|
||||||
|
|||||||
Reference in New Issue
Block a user