Compare commits

..

36 Commits

Author SHA1 Message Date
Tian Dai
50a4349a84 Merge branch 'dev' into feature-auto-lookup
# Conflicts:
#	frontend/src/components/AppFieldSelectBox.vue
#	frontend/src/components/right/AppFieldSelect.vue
#	plugin/kintone-addins/package.json
#	plugin/kintone-addins/src/actions/auto-lookup.ts
#	plugin/kintone-addins/src/types/action-process.ts
#	plugin/kintone-addins/vite.config.js
2024-07-08 15:21:39 +09:00
Mouriya
eb50f72df9 Merge commit '3540becf6f657ee6ab820f18c63b3b59c4f54c25' into feature-auto-lookup 2024-07-02 12:17:07 +09:00
Mouriya
3540becf6f vite-plugin-css-injected-by-jsはメンテナンスされていないため、通常のソースマップ生成に影響を与えるので、vite-plugin-lib-injected-cssを使用してください 2024-07-02 12:15:18 +09:00
Mouriya
5ca16d7b45 自動検索プラグインを追加 2024-07-01 16:20:58 +09:00
Mouriya
9d2217f8e1 ログの削除 2024-07-01 04:08:28 +09:00
Mouriya
704aab9265 スペルミスの修正 2024-07-01 04:07:53 +09:00
Mouriya
046ef4cb9f APPフィールドコンポーネントのバグ修正 2024-07-01 03:53:49 +09:00
Mouriya
d2f271e3cd エントリーを追加するときにデータを統合する 2024-06-17 15:22:10 +09:00
Mouriya
5fdb23d6d5 フィールドの生のjsonをビューに直接表示する。 2024-06-17 15:20:32 +09:00
Mouriya
734adf9a1e 空リストの修正 2024-06-17 15:19:36 +09:00
Mouriya
0e8d1957a3 ユーザーが手動でフィールドリストを追加または削除する必要はなくなり、プログラムが自動的にアプリのすべてのフィールドに対してリストを作成します。 2024-06-17 03:18:52 +09:00
Mouriya
e2a625ba12 入力ボックスの入力可否の設定を削除し、特定のボタン入力後に入力ボックスの入力可否に変更する。 2024-06-17 03:16:26 +09:00
Mouriya
eb89b3f8a6 Merge commit '26a685b872daa65a069ad8c39ef4b973c8e25022' into feature-data-mapping 2024-06-17 00:48:01 +09:00
Mouriya
343f97234a バグ修正:json文字列フェッチの問題 2024-06-10 12:34:01 +09:00
Mouriya
04f28a3be5 新しい統合されたフィールド入力、すべての関連部品の一致修正. フィールドの値を取得する に新しいアクションを追加 2024-06-10 06:10:32 +09:00
Tian Dai
63099eda8b Merge branch 'plugin-infar-vite' of ssh.dev.azure.com:v3/alicorn-dev/KintoneAppBuilder/KintoneAppBuilder into feature-data-mapping 2024-06-04 17:49:32 +09:00
Tian Dai
65d89b0462 Windowsのオペレーティングシステムの権限問題のため、Viteの自動URLオープン機能を無効にしました 2024-06-04 17:48:39 +09:00
Tian Dai
c6ded099fa vite devとvite serverはエイリアスではなく、置き換え可能で、問題を修正しました。 2024-06-04 17:41:09 +09:00
Tian Dai
c072233593 Merge branch 'plugin-infar-vite' into feature-data-mapping
# Conflicts:
#	plugin/kintone-addins/package.json
#	plugin/kintone-addins/vite.config.js
2024-06-04 17:21:43 +09:00
Tian Dai
4e296c1555 npm-run-all2を全オペレーティング・システムと依存性管理のサポートに置き換える。ラン・スクリプトをより組み合わせ可能なものに再編成する。 プロジェクトの dotenv サポートを提供する。 2024-06-04 16:16:36 +09:00
016fcaab29 feat:データマッピングアクション変更 2024-06-03 17:39:39 +09:00
Mouriya
bebc1ec9fa フィックス 2024-06-03 08:10:23 +09:00
Mouriya
f71c3d2123 挿入専用のデータ・マッピング・プラグインを追加 2024-06-03 08:08:06 +09:00
Mouriya
d79ce8d06b データ収集プラグインの追加 2024-06-03 07:08:04 +09:00
Mouriya
fc9c3a5e81 条件演算子をカスタマイズし、kintoneクエリ文字列に変換することができます。 2024-06-03 07:07:20 +09:00
Mouriya
6df72a1ae3 Merge commit '372dbe50f7254ed3142a85dac58e624fce695aa7' into feature-data-mapping 2024-06-03 02:16:50 +09:00
Mouriya
372dbe50f7 HTTPサーバーのホットリロード機能を追加。 2024-06-03 02:08:37 +09:00
Mouriya
68fde6d490 Merge commit 'b25c17ab53a848f5692f113c6c3c1177e310d87f' into feature-data-mapping 2024-06-03 00:41:01 +09:00
Mouriya
c398dee21e 誤ったmodelValueの使用法の修正 2024-05-27 19:52:16 +09:00
Mouriya
f2ab310b6d Merge commit 'a6cf95b76d56841e7a5d545c8f0835e44cf4dafc' into feature-data-mapping 2024-05-27 19:27:44 +09:00
Mouriya
ca0f24465b 外部アプリセレクタコンポーネントがある場合、このコンポーネントはアプリを選択せずにフィールドを選択できる。 2024-05-27 19:04:21 +09:00
Mouriya
3cc4b65460 アプリ選択コンポーネントがある場合、アプリまたはフィールドが選択されるまで、それらを無効にすることができる。 2024-05-27 19:03:08 +09:00
Mouriya
a6cf95b76d 新しいアプリ選択コンポーネント 2024-05-27 18:45:34 +09:00
Mouriya
484ab9fdae ファイル名とコンポーネント名を変更し、コンポーネントとして使用できるようにする。 2024-05-27 18:44:36 +09:00
Mouriya
78bba2502f データ・マッピング・コンポーネントの追加 2024-05-25 07:01:58 +09:00
Mouriya
c78b3cb5c0 AppFieldSelectコンポーネントは、パブリック部分をAppFieldSelectBoxとして抽出する。 2024-05-25 07:01:38 +09:00
29 changed files with 840 additions and 1287 deletions

File diff suppressed because one or more lines are too long

View File

@@ -13,6 +13,7 @@ API_V1_AUTH_KEY = "X-Cybozu-Authorization"
DEPLOY_MODE = "PROD" #DEV,PROD DEPLOY_MODE = "PROD" #DEV,PROD
DEPLOY_JS_URL = "https://ka-addin.azurewebsites.net/alc_runtime.js" DEPLOY_JS_URL = "https://ka-addin.azurewebsites.net/alc_runtime.js"
#DEPLOY_JS_URL = "https://ce1c-133-139-70-194.ngrok-free.app/alc_runtime.js"
KINTONE_FIELD_TYPE=["GROUP","GROUP_SELECT","CHECK_BOX","SUBTABLE","DROP_DOWN","USER_SELECT","RADIO_BUTTON","RICH_TEXT","LINK","REFERENCE_TABLE","CALC","TIME","NUMBER","ORGANIZATION_SELECT","FILE","DATETIME","DATE","MULTI_SELECT","SINGLE_LINE_TEXT","MULTI_LINE_TEXT"] KINTONE_FIELD_TYPE=["GROUP","GROUP_SELECT","CHECK_BOX","SUBTABLE","DROP_DOWN","USER_SELECT","RADIO_BUTTON","RICH_TEXT","LINK","REFERENCE_TABLE","CALC","TIME","NUMBER","ORGANIZATION_SELECT","FILE","DATETIME","DATE","MULTI_SELECT","SINGLE_LINE_TEXT","MULTI_LINE_TEXT"]

View File

@@ -33,7 +33,7 @@
<div class="row"> <div class="row">
<field-select ref="fieldDlg" name="フィールド" :type="selectType" :updateSelectFields="updateSelectFields" <field-select ref="fieldDlg" name="フィールド" :type="selectType" :updateSelectFields="updateSelectFields"
:appId="selField?.app?.id" not_page :filter="fieldFilter" :appId="selField?.app?.id" not_page :filter="fieldFilter"
:selectedFields="selField.fields" :fieldTypes="fieldTypes"></field-select> :selectedFields="selField.fields"></field-select>
</div> </div>
</div> </div>
</div> </div>
@@ -92,10 +92,7 @@ export default defineComponent({
type: String, type: String,
default: 'single' default: 'single'
}, },
fieldTypes:{
type:Array,
default:()=>[]
}
}, },
setup(props, { emit }) { setup(props, { emit }) {
const showSelectApp = ref(false); const showSelectApp = ref(false);

View File

@@ -1,14 +1,14 @@
<template> <template>
<q-field labelColor="primary" class="condition-object" dense outlined :label="label" :disable="disabled" <q-field labelColor="primary" class="condition-object" :clearable="isSelected" stack-label :dense="true"
:clearable="isSelected"> :outlined="true">
<template v-slot:control> <template v-slot:control>
<q-chip color="primary" text-color="white" v-if="isSelected && selectedObject.objectType==='field'" :dense="true" class="selected-obj"> <!-- <q-chip color="primary" text-color="white" v-if="isSelected && selectedObject.objectType==='field'" :dense="true" class="selected-obj">
{{ selectedObject.name }} {{ selectedObject.name }}
</q-chip> </q-chip>
<q-chip color="info" text-color="white" v-if="isSelected && selectedObject.objectType==='variable'" :dense="true" class="selected-obj"> <q-chip color="info" text-color="white" v-if="isSelected && selectedObject.objectType==='variable'" :dense="true" class="selected-obj">
{{ selectedObject.name.name }} {{ selectedObject.name.name }}
</q-chip> </q-chip> -->
<div v-if="isSelected && selectedObject.objectType==='text'">{{ selectedObject?.sharedText }}</div> {{ selectedObject?.sharedText }}
</template> </template>
<template v-slot:append> <template v-slot:append>
<q-icon name="search" class="cursor-pointer" @click="showDg" /> <q-icon name="search" class="cursor-pointer" @click="showDg" />
@@ -25,21 +25,17 @@
<condition-objects ref="appDg" name="フィールド" type="single" :filter="filter" :appId="store.appInfo?.appId" :vars="vars"></condition-objects> <condition-objects ref="appDg" name="フィールド" type="single" :filter="filter" :appId="store.appInfo?.appId" :vars="vars"></condition-objects>
--> -->
<DynamicItemInput v-model:selectedObject="selectedObject" :canInput="config.canInput" <DynamicItemInput v-model:selectedObject="selectedObject" :canInput="config.canInput"
:buttonsConfig="config.buttonsConfig" :appId="store.appInfo?.appId" :options="options" ref="inputRef" /> :buttonsConfig="config.buttonsConfig" :appId="store.appInfo?.appId" />
</show-dialog> </show-dialog>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, reactive, ref, watchEffect, computed ,PropType} from 'vue'; import { defineComponent, reactive, ref, watchEffect, computed } from 'vue';
import ShowDialog from '../ShowDialog.vue'; import ShowDialog from '../ShowDialog.vue';
// import ConditionObjects from '../ConditionObjects.vue'; // import ConditionObjects from '../ConditionObjects.vue';
import DynamicItemInput from '../DynamicItemInput/DynamicItemInput.vue'; import DynamicItemInput from '../DynamicItemInput/DynamicItemInput.vue';
import { useFlowEditorStore } from '../../stores/flowEditor'; import { useFlowEditorStore } from '../../stores/flowEditor';
import { IActionFlow, IActionNode, IActionVariable } from '../../types/ActionTypes'; import { IActionFlow, IActionNode, IActionVariable } from '../../types/ActionTypes';
import { IDynamicInputConfig } from 'src/types/ComponentTypes';
export default defineComponent({ export default defineComponent({
name: 'ConditionObject', name: 'ConditionObject',
components: { components: {
@@ -48,16 +44,8 @@ export default defineComponent({
// ConditionObjects // ConditionObjects
}, },
props: { props: {
disabled: {
type: Boolean,
default: false
},
label: {
type: String,
default: undefined
},
config: { config: {
type: Object as PropType<IDynamicInputConfig>, type: Object,
default: () => { default: () => {
return { return {
canInput: false, canInput: false,
@@ -68,12 +56,6 @@ export default defineComponent({
}; };
} }
}, },
options:
{
type:Array as PropType< string[]>,
default:()=>[]
},
modelValue: { modelValue: {
type: Object, type: Object,
default: null default: null
@@ -81,13 +63,12 @@ export default defineComponent({
}, },
setup(props, { emit }) { setup(props, { emit }) {
// const appDg = ref(); // const appDg = ref();
const inputRef=ref();
const show = ref(false); const show = ref(false);
const selectedObject = ref(props.modelValue); const selectedObject = ref(props.modelValue);
const store = useFlowEditorStore(); const store = useFlowEditorStore();
// const sharedText = ref(''); // 共享的文本状态 // const sharedText = ref(''); // 共享的文本状态
const isSelected = computed(() => { const isSelected = computed(() => {
return selectedObject.value?.sharedText !== ''; return selectedObject?.value?.sharedText !== '';
}); });
// const isSelected = computed(()=>{ // const isSelected = computed(()=>{
// return selectedObject.value!==null && typeof selectedObject.value === 'object' && ('name' in selectedObject.value) // return selectedObject.value!==null && typeof selectedObject.value === 'object' && ('name' in selectedObject.value)
@@ -104,7 +85,6 @@ export default defineComponent({
const closeDg = (val: string) => { const closeDg = (val: string) => {
if (val == 'OK') { if (val == 'OK') {
// selectedObject.value = appDg.value.selected[0]; // selectedObject.value = appDg.value.selected[0];
selectedObject.value = inputRef.value.selectedObjectRef
} }
}; };
@@ -113,7 +93,6 @@ export default defineComponent({
}); });
return { return {
inputRef,
store, store,
// appDg, // appDg,
show, show,

View File

@@ -69,19 +69,17 @@
<div class="row no-wrap items-center q-my-xs"> <div class="row no-wrap items-center q-my-xs">
<ConditionObject v-bind="prop.node" v-model="prop.node.object" :config="leftDynamicItemConfig" class="col-4"/> <ConditionObject v-bind="prop.node" v-model="prop.node.object" :config="leftDynamicItemConfig" class="col-4"/>
<q-select v-model="prop.node.operator" :options="operators" class="operator" :outlined="true" :dense="true"></q-select> <q-select v-model="prop.node.operator" :options="operators" class="operator" :outlined="true" :dense="true"></q-select>
<ConditionObject v-bind="prop.node" v-model="prop.node.value" :config="rightDynamicItemConfig" class="col-4" <ConditionObject v-bind="prop.node" v-model="prop.node.value" :config="rightDynamicItemConfig" class="col-4"/>
:options="objectValueOptions(prop.node?.object?.options)"
/>
<!-- <ConditionObject v-bind="prop.node" v-model="prop.node.object" class="col-4"/> --> <!-- <ConditionObject v-bind="prop.node" v-model="prop.node.object" class="col-4"/> -->
<!-- <q-input v-if="!prop.node.object || !('options' in prop.node.object)" <!-- <q-input v-if="!prop.node.object || !('options' in prop.node.object)"
v-model="prop.node.value" v-model="prop.node.value"
class="condition-value" :outlined="true" :dense="true" ></q-input> --> class="condition-value" :outlined="true" :dense="true" ></q-input> -->
<!-- <q-select v-if="prop.node.object && ('options' in prop.node.object)" <q-select v-if="prop.node.object && ('options' in prop.node.object)"
v-model="prop.node.value" v-model="prop.node.value"
:options="objectValueOptions(prop.node.object.options)" :options="objectValueOptions(prop.node.object.options)"
clearable clearable
value-key="index" value-key="index"
class="condition-value" :outlined="true" :dense="true" ></q-select> --> class="condition-value" :outlined="true" :dense="true" ></q-select>
<q-btn flat round dense icon="more_horiz" size="sm" > <q-btn flat round dense icon="more_horiz" size="sm" >
<q-menu auto-close anchor="top right"> <q-menu auto-close anchor="top right">
<q-list> <q-list>
@@ -120,7 +118,6 @@ import { finished } from 'stream';
import { defineComponent,ref,reactive, computed, inject } from 'vue'; import { defineComponent,ref,reactive, computed, inject } from 'vue';
import { INode,ConditionTree,GroupNode,ConditionNode, LogicalOperator,Operator,NodeType } from '../../types/Conditions'; import { INode,ConditionTree,GroupNode,ConditionNode, LogicalOperator,Operator,NodeType } from '../../types/Conditions';
import ConditionObject from './ConditionObject.vue'; import ConditionObject from './ConditionObject.vue';
import { IDynamicInputConfig } from 'src/types/ComponentTypes';
export default defineComponent( { export default defineComponent( {
name: 'NodeCondition', name: 'NodeCondition',
components: { components: {
@@ -148,18 +145,17 @@ export default defineComponent( {
return opts; return opts;
}); });
const operatorSet = inject<Array<any>>('Operator') const operator = inject('Operator')
const operators = ref(operatorSet ? operatorSet : Object.values(Operator)); const operators =computed(()=>{
return operator ? operator : Object.values(Operator);
});
const tree = reactive(props.conditionTree); const tree = reactive(props.conditionTree);
const conditionString = computed(()=>{ const conditionString = computed(()=>{
return tree.buildConditionString(tree.root); return tree.buildConditionString(tree.root);
}); });
const objectValueOptions=(options:any):any[]|null=>{ const objectValueOptions=(options:any):any[]=>{
if(!options){
return null;
}
const opts:any[] =[]; const opts:any[] =[];
Object.keys(options).forEach((key) => Object.keys(options).forEach((key) =>
{ {
@@ -226,14 +222,13 @@ export default defineComponent( {
ticked.value=[]; ticked.value=[];
} }
const expanded=computed(()=>tree.getGroups(tree.root)); const expanded=computed(()=>tree.getGroups(tree.root));
// addCondition(tree.root); // addCondition(tree.root);
const leftDynamicItemConfig = inject<IDynamicInputConfig>('leftDynamicItemConfig');
const rightDynamicItemConfig = inject<IDynamicInputConfig>('rightDynamicItemConfig');
return { return {
leftDynamicItemConfig, leftDynamicItemConfig :inject('leftDynamicItemConfig'),
rightDynamicItemConfig, rightDynamicItemConfig:inject('rightDynamicItemConfig'),
showingCondition, showingCondition,
conditionString, conditionString,
tree, tree,
@@ -265,12 +260,10 @@ export default defineComponent( {
max-height: 40px; max-height: 40px;
margin: 0 2px; margin: 0 2px;
} }
.operator{ .operator{
min-width: 150px; min-width: 150px;
max-height: 40px; max-height: 40px;
margin: 0 2px; margin: 0 2px;
text-align: center; text-align: center;
font-size: 12pt; font-size: 12pt;
} }

View File

@@ -2,30 +2,13 @@
<div class="q-mx-md" style="max-width: 600px;"> <div class="q-mx-md" style="max-width: 600px;">
<!-- <q-card> --> <!-- <q-card> -->
<div class="q-mb-md"> <div class="q-mb-md">
<q-input ref="inputRef" v-if="!optionsRef|| optionsRef.length===0" <q-input ref="inputRef" outlined dense debounce="200" @update:model-value="updateSharedText"
outlined dense debounce="200" @update:model-value="updateSharedText" v-model="sharedText" :readonly="!canInput">
v-model="sharedText" :readonly="!canInputFlag" autogrow>
<template v-slot:append> <template v-slot:append>
<q-btn flat round padding="none" icon="cancel" @click="clearSharedText" color="grey-6" /> <q-btn flat round padding="none" icon="cancel" @click="clearSharedText" color="grey-6" />
</template> </template>
</q-input> </q-input>
<q-select v-if="optionsRef && optionsRef.length>0"
:model-value="sharedText"
:options="optionsRef"
clearable
value-key="index"
outlined
dense
use-input
hide-selected
input-debounce="10"
fill-input
@input-value="setValue"
@clear="sharedText=null"
hide-dropdown-icon
:readonly="!canInputFlag"
>
</q-select>
</div> </div>
<div class="row q-gutter-sm"> <div class="row q-gutter-sm">
@@ -51,12 +34,18 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { ref, inject, watchEffect, defineComponent,PropType } from 'vue'; import { ref, inject, watchEffect, defineComponent } from 'vue';
import FieldAdd from './FieldAdd.vue'; import FieldAdd from './FieldAdd.vue';
import VariableAdd from './VariableAdd.vue'; import VariableAdd from './VariableAdd.vue';
// import FunctionAdd from './FunctionAdd.vue'; // import FunctionAdd from './FunctionAdd.vue';
import ShowDialog from '../ShowDialog.vue'; import ShowDialog from '../ShowDialog.vue';
import { IButtonConfig } from 'src/types/ComponentTypes';
type ButtonConfig = {
label: string;
color: string;
type: string;
editable: boolean;
};
export default defineComponent({ export default defineComponent({
name: 'DynamicItemInput', name: 'DynamicItemInput',
@@ -67,21 +56,18 @@ export default defineComponent({
ShowDialog ShowDialog
}, },
props: { props: {
canInput: { // canInput: {
type: Boolean, // type: Boolean,
default: false // default: false
}, // },
appId: { appId: {
type: String, type: String,
}, },
selectedObject: { selectedObject: {
default: {} default: {}
}, },
options:{
type:Array as PropType< string[]>
},
buttonsConfig: { buttonsConfig: {
type: Array as PropType<IButtonConfig[]>, type: Array as () => ButtonConfig[],
default: () => [ default: () => [
{ label: 'フィールド', color: 'primary', type: 'FieldAdd' } { label: 'フィールド', color: 'primary', type: 'FieldAdd' }
] ]
@@ -91,70 +77,64 @@ export default defineComponent({
const filter = ref(''); const filter = ref('');
const dialogVisible = ref(false); const dialogVisible = ref(false);
const currentDialogName = ref(''); const currentDialogName = ref('');
const selectedObjectRef = ref(props.selectedObject);
const currentComponent = ref('FieldAdd'); const currentComponent = ref('FieldAdd');
const sharedText = ref(props.selectedObject?.sharedText ?? ''); const sharedText = ref(props.selectedObject?.sharedText ?? '');
const inputRef = ref(); const inputRef = ref();
const canInputFlag = ref(props.canInput); const canInput = ref(true);
const editable = ref(false); const editable = ref(false);
const openDialog = (button: IButtonConfig) => { const openDialog = (button: ButtonConfig) => {
currentDialogName.value = button.label; currentDialogName.value = button.label;
currentComponent.value = button.type; currentComponent.value = button.type;
dialogVisible.value = true; dialogVisible.value = true;
editable.value = canInputFlag.value; editable.value = button.editable ?? true;
}; };
const closeDialog = () => { const closeDialog = () => {
dialogVisible.value = false; dialogVisible.value = false;
}; };
const handleSelect = (value:any) => { const handleSelect = (value) => {
// 获取当前光标位置
// const cursorPosition = inputRef.value.getNativeElement().selectionStart;
// if (cursorPosition === undefined || cursorPosition === 0) {
sharedText.value = `${value._t}`;
// } else {
// const textBefore = sharedText.value.substring(0, cursorPosition);
// const textAfter = sharedText.value.substring(cursorPosition);
// sharedText.value = `${textBefore}${value._t}${textAfter}`;
// }
if (value && value._t && (value._t as string).length > 0) { if (value && value._t && (value._t as string).length > 0) {
canInputFlag.value = editable.value; canInput.value = editable.value;
} }
selectedObjectRef.value={ sharedText: value._t, ...value }; emit('update:selectedObject', { sharedText: sharedText.value, ...value });
sharedText.value = `${value._t}`;
// emit('update:selectedObject', { sharedText: sharedText.value, ...value });
dialogVisible.value = false; dialogVisible.value = false;
}; };
const clearSharedText = () => { const clearSharedText = () => {
sharedText.value = ''; sharedText.value = '';
selectedObjectRef.value={}; canInput.value = true;
canInputFlag.value = true; emit('update:selectedObject', {});
// emit('update:selectedObject', {});
} }
const updateSharedText = (value:string) => { const updateSharedText = (value) => {
sharedText.value = value; sharedText.value = value;
selectedObjectRef.value= { sharedText: value,objectType:'text' } emit('update:selectedObject', { ...props.selectedObject, sharedText: value });
// emit('update:selectedObject', { ...props.selectedObject, sharedText: value,objectType:'text' });
} }
const setValue=(value:string)=>{
sharedText.value = value;
if(selectedObjectRef.value.sharedText!==value){
selectedObjectRef.value= { sharedText: value,objectType:'text' }
}
}
const optionsRef=ref(props.options);
return { return {
filter, filter,
dialogVisible, dialogVisible,
currentDialogName, currentDialogName,
currentComponent, currentComponent,
canInputFlag, canInput,
openDialog, openDialog,
closeDialog, closeDialog,
handleSelect, handleSelect,
clearSharedText, clearSharedText,
updateSharedText, updateSharedText,
setValue,
sharedText, sharedText,
inputRef, inputRef
optionsRef,
selectedObjectRef
}; };
} }
}); });

View File

@@ -49,7 +49,7 @@
</q-card> </q-card>
</div> </div>
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeAFBox"> <show-dialog v-model:visible="show" name="フィールド一覧" @close="closeAFBox">
<AppFieldSelectBox v-model:selectedField="selectedField" :selectType="selectType" ref="afBox" :fieldTypes="fieldTypes"/> <AppFieldSelectBox v-model:selectedField="selectedField" :selectType="selectType" ref="afBox"/>
</show-dialog> </show-dialog>
</template> </template>
@@ -66,8 +66,7 @@ export interface IApp {
export interface IField { export interface IField {
name: string, name: string,
code: string, code: string,
type: string, type: string
label?:string
} }
export interface IAppFields { export interface IAppFields {
@@ -102,10 +101,6 @@ export default defineComponent({
selectType: { selectType: {
type: String, type: String,
default: 'single' default: 'single'
},
fieldTypes:{
type:Array,
default:()=>[]
} }
}, },
setup(props, { emit }) { setup(props, { emit }) {

View File

@@ -18,13 +18,38 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { ConditionNode, ConditionTree, Operator, OperatorListItem } from 'app/src/types/Conditions'; import { ConditionNode, ConditionTree, Operator, OperatorListItem } from 'app/src/types/Conditions';
import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue'; import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue';
import ConditionEditor from '../ConditionEditor/ConditionEditor.vue'; import ConditionEditor from '../ConditionEditor/ConditionEditor.vue';
import { IActionProperty } from 'src/types/ActionTypes';
import { } from 'src/types/';
type Props = {
props?: {
name: string;
modelValue?: {
app: {
id: string;
name: string;
},
fields: {
type: string;
label: string;
code: string;
}[]
}
}
};
type InputConfg = {
canInput: boolean;
buttonsConfig: {
label: string;
color: string;
type: string;
}[]
};
export default defineComponent({ export default defineComponent({
@@ -35,7 +60,7 @@ export default defineComponent({
}, },
props: { props: {
context: { context: {
type: Array<IActionProperty>, type: Array<Props>,
default: '', default: '',
}, },
displayName: { displayName: {
@@ -90,7 +115,7 @@ export default defineComponent({
}, },
setup(props, { emit }) { setup(props, { emit }) {
const source = props.context.find(element => element.props.name === 'sources') const source = props.context.find(element => element?.props?.name === 'sources')
if (source) { if (source) {
if (props.sourceType === 'field') { if (props.sourceType === 'field') {

View File

@@ -16,37 +16,31 @@
</q-card> </q-card>
</template> </template>
</q-field> </q-field>
<show-dialog v-model:visible="dgIsShow" name="データマッピング" @close="closeDg" min-width="55vw" min-height="60vh"> <show-dialog v-model:visible="dgIsShow" name="データマッピング" @close="closeDg" min-width="50vw" min-height="60vh">
<div class=""> <div class="q-mx-md">
<div class="row q-col-gutter-x-xs flex-center"> <div class="row q-col-gutter-x-xs flex-center">
<div class="col-5"> <div class="col-6">
<div class="q-mx-xs">ソース</div> <div class="q-mx-xs">ソース</div>
</div> </div>
<!-- <div class="col-1"> <!-- <div class="col-1">
</div> --> </div> -->
<div class="col-5"> <div class="col-6">
<div class="row justify-between q-mr-md"> <div class="q-mx-xs">目標</div>
<div class="">{{ sourceApp?.name }}</div>
<q-btn outline color="primary" size="xs" label="最新のフィールドを取得する"
@click="() => updateFields(sourceAppId!)" />
</div> </div>
<!-- <div class="col-1"><q-btn flat round dense icon="add" size="sm" @click="addMappingObject" /> -->
<!-- </div> -->
</div> </div>
<div class="col-1 q-pl-sm"> <q-virtual-scroll style="max-height: 75vh;" :items="mappingProps" separator v-slot="{ item, index }">
キー
</div>
</div>
<q-virtual-scroll style="max-height: 60vh;" :items="mappingProps" separator v-slot="{ item, index }">
<!-- <div class="q-my-sm" v-for="(item, index) in mappingProps" :key="item.id"> --> <!-- <div class="q-my-sm" v-for="(item, index) in mappingProps" :key="item.id"> -->
<div class="row q-pa-sm q-col-gutter-x-md flex-center"> <div class="row q-my-md q-col-gutter-x-md flex-center">
<div class="col-5"> <div class="col-6">
<ConditionObject :config="config" v-model="item.from" :disabled="item.disabled" <ConditionObject :config="config" v-model="item.from" />
:label="item.disabled ? '「Lookup」によってロックされる' : undefined" />
</div> </div>
<!-- <div class="col-1"> <!-- <div class="col-1">
</div> --> </div> -->
<div class="col-5"> <div class="col-6">
<q-field v-model="item.vName" type="text" outlined dense :disable="item.disabled" > <q-field v-model="item.vName" type="text" outlined dense>
<!-- <template v-slot:append> <!-- <template v-slot:append>
<q-icon name="search" class="cursor-pointer" <q-icon name="search" class="cursor-pointer"
@click="() => { mappingProps[index].to.isDialogVisible = true }" /> @click="() => { mappingProps[index].to.isDialogVisible = true }" />
@@ -55,23 +49,19 @@
<div class="self-center full-width no-outline" tabindex="0" <div class="self-center full-width no-outline" tabindex="0"
v-if="item.to.app?.name && item.to.fields?.length > 0 && item.to.fields[0].label"> v-if="item.to.app?.name && item.to.fields?.length > 0 && item.to.fields[0].label">
{{ `${item.to.fields[0].label}` }} {{ `${item.to.fields[0].label}` }}
<span class="text-red" v-if="item.to.fields[0].required">*</span> <q-tooltip>
<q-tooltip class="bg-yellow-2 text-black shadow-4" >
<div>アプリ : {{ item.to.app.name }}</div> <div>アプリ : {{ item.to.app.name }}</div>
<div>フィールドのコード : {{ item.to.fields[0].code }}</div> <div>フィールドのコード : {{ item.to.fields[0].code }}</div>
<div>フィールドのタイプ : {{ item.to.fields[0].type }}</div> <div>フィールドのタイプ : {{ item.to.fields[0].type }}</div>
<div v-if="item.to.fields[0].required">必須項目</div> <div>フィールド : {{ item.to.fields[0] }}</div>
<!-- <div>フィールド : {{ item.to.fields[0] }}</div>
<div>フィールド : {{ item.isKey }}</div> -->
</q-tooltip> </q-tooltip>
</div> </div>
</template> </template>
</q-field> </q-field>
</div> </div>
<div class="col-1"> <!-- <div class="col-1">
<q-checkbox size="sm" v-model="item.isKey" :disable="item.disabled" /> <q-btn flat round dense icon="delete" size="sm" @click="() => deleteMappingObject(index)" />
<!-- <q-btn flat round dense icon="delete" size="sm" @click="() => deleteMappingObject(index)" /> --> </div> -->
</div>
</div> </div>
<show-dialog v-model:visible="mappingProps[index].to.isDialogVisible" name="フィールド一覧" <show-dialog v-model:visible="mappingProps[index].to.isDialogVisible" name="フィールド一覧"
@@ -84,10 +74,6 @@
</show-dialog> </show-dialog>
<!-- </div> --> <!-- </div> -->
</q-virtual-scroll> </q-virtual-scroll>
<div class="q-mt-lg q-ml-md row ">
<q-checkbox size="sm" v-model="createWithNull" label="キーが存在しない場合は新規に作成され、存在する場合はデータが更新されます。" />
</div>
</div> </div>
</show-dialog> </show-dialog>
</div> </div>
@@ -100,10 +86,10 @@ import ConditionObject from '../ConditionEditor/ConditionObject.vue';
import ShowDialog from '../ShowDialog.vue'; import ShowDialog from '../ShowDialog.vue';
import AppFieldSelectBox from '../AppFieldSelectBox.vue'; import AppFieldSelectBox from '../AppFieldSelectBox.vue';
import FieldSelect from '../FieldSelect.vue'; import FieldSelect from '../FieldSelect.vue';
import { IApp, IField } from './AppFieldSelect.vue'; import IAppFields from './AppFieldSelect.vue';
import { api } from 'boot/axios'; import { api } from 'boot/axios';
type ContextProps = { type Props = {
props?: { props?: {
name: string; name: string;
modelValue?: { modelValue?: {
@@ -114,25 +100,14 @@ type ContextProps = {
} }
} }
}; };
type ValueType = {
type CurrentModelValueType = {
data: MappingValueType[];
createWithNull: boolean;
}
type MappingValueType = {
id: string; id: string;
from: { sharedText?: string }; from: object;
to: { to: typeof IAppFields & {
app?: IApp,
fields: IField[],
isDialogVisible: boolean; isDialogVisible: boolean;
}; };
isKey: boolean;
disabled: boolean;
} }
const blackListLabelName = ['レコード番号', '作業者', '更新者', '更新日時', '作成日時', '作成者']
export default defineComponent({ export default defineComponent({
name: 'DataMapping', name: 'DataMapping',
@@ -145,7 +120,7 @@ export default defineComponent({
}, },
props: { props: {
context: { context: {
type: Array<ContextProps>, type: Array<Props>,
default: '', default: '',
}, },
displayName: { displayName: {
@@ -157,7 +132,7 @@ export default defineComponent({
default: '', default: '',
}, },
modelValue: { modelValue: {
type: Object as () => CurrentModelValueType, type: Object as () => ValueType[],
}, },
placeholder: { placeholder: {
type: String, type: String,
@@ -166,11 +141,7 @@ export default defineComponent({
onlySourceSelect: { onlySourceSelect: {
type: Boolean, type: Boolean,
default: false default: false
}, }
fieldTypes:{
type:Array,
default:()=>[]
},
}, },
setup(props, { emit }) { setup(props, { emit }) {
@@ -181,62 +152,58 @@ export default defineComponent({
const sourceAppId = computed(() => sourceApp.value?.id); const sourceAppId = computed(() => sourceApp.value?.id);
const closeDg = () => { const closeDg = () => {
emit('update:modelValue', { data: mappingProps.value, createWithNull: createWithNull.value }); emit('update:modelValue', mappingProps.value
);
} }
const closeToDg = () => { const closeToDg = () => {
emit('update:modelValue', { data: mappingProps.value, createWithNull: createWithNull.value }); emit('update:modelValue', mappingProps.value
);
} }
const mappingProps = ref(props.modelValue?.data ?? []); const mappingProps = computed(() => props.modelValue ?? []);
const createWithNull = ref(props.modelValue?.createWithNull ?? false) watch(() => sourceAppId.value, async (newId, oldId) => {
// 外部ソースコンポーネントの appid をリッスンし、変更されたときに現在のコンポーネントを更新します
watch(() => sourceAppId.value, async (newId,) => {
if (!newId) return; if (!newId) return;
updateFields(newId) const a = await api.get('api/v1/appfields', {
})
const updateFields = async (sourceAppId: string) => {
const ktAppFields = await api.get('api/v1/appfields', {
params: { params: {
app: sourceAppId app: newId
} }
}).then(res => { }).then(res => {
return Object.values(res.data.properties) return Object.values(res.data.properties)
// kintoneのデフォルトの非表示フィールドフィルタリング
.filter(f => !blackListLabelName.find(label => f.label === label))
.map(f => ({ name: f.label, objectType: 'field', ...f })) .map(f => ({ name: f.label, objectType: 'field', ...f }))
.map(f => { .map(f => {
// 更新前の値を求める
const beforeData = mappingProps.value.find(m => m.to.fields[0].code === f.code)
return { return {
id: uuidv4(), id: uuidv4(),
from: beforeData?.from ?? {}, // 以前のデータを入力します from: {},
to: { to: {
app: sourceApp.value, app: sourceApp.value,
fields: [f], fields: [f],
isDialogVisible: false isDialogVisible: false
}, }
isKey: beforeData?.isKey ?? false, // 以前のデータを入力します
disabled: false
} }
}) })
}) })
const modelValue = props.modelValue ?? [];
// 「ルックアップ」によってロックされているフィールドを検索する if (modelValue.length === 0 || newId !== oldId) {
const lookupFixedField = ktAppFields emit('update:modelValue', a);
.filter(field => field.to.fields[0].lookup !== undefined) return;
.flatMap(field => field.to.fields[0].lookup.fieldMappings.map((m) => m.field))
// 「ルックアップ」でロックされたビューコンポーネントを非対話型に設定します
if (lookupFixedField.length > 0) {
ktAppFields.filter(f => lookupFixedField.includes(f.to.fields[0].code)).forEach(f => f.disabled = true)
} }
const modelValueFieldNames = modelValue.map(item => item.to.fields[0].name);
mappingProps.value = ktAppFields const newFields = a.filter(field => !modelValueFieldNames.includes(field.to.fields[0].name));
}
const updatedModelValue = [...modelValue, ...newFields];
emit('update:modelValue', updatedModelValue);
})
console.log(mappingProps.value);
// const deleteMappingObject = (index: number) => mappingProps.length === 1
// ? mappingProps.splice(0, mappingProps.length, defaultMappingProp())
// : mappingProps.splice(index, 1);
const mappingObjectsInputDisplay = computed(() => const mappingObjectsInputDisplay = computed(() =>
(mappingProps.value && Array.isArray(mappingProps.value)) ? (mappingProps.value && Array.isArray(mappingProps.value)) ?
@@ -248,12 +215,15 @@ export default defineComponent({
: [] : []
); );
const btnDisable = computed(() => props.onlySourceSelect ? !(source?.props?.modelValue?.app?.id) : false); const btnDisable = computed(() => props.onlySourceSelect ? !(source?.props?.modelValue?.app?.id) : false);
watchEffect(() => { //集計処理方法
emit('update:modelValue', { data: mappingProps.value, createWithNull: createWithNull.value });
});
watchEffect(() => {
emit('update:modelValue', mappingProps.value);
});
return { return {
uuidv4, uuidv4,
dgIsShow: ref(false), dgIsShow: ref(false),
@@ -261,8 +231,6 @@ export default defineComponent({
toDgIsShow: ref(false), toDgIsShow: ref(false),
closeToDg, closeToDg,
mappingProps, mappingProps,
createWithNull,
updateFields,
// addMappingObject: () => mappingProps.push(defaultMappingProp()), // addMappingObject: () => mappingProps.push(defaultMappingProp()),
// deleteMappingObject, // deleteMappingObject,
mappingObjectsInputDisplay, mappingObjectsInputDisplay,
@@ -272,13 +240,11 @@ export default defineComponent({
config: { config: {
canInput: false, canInput: false,
buttonsConfig: [ buttonsConfig: [
{ label: 'フィールド', color: 'primary', type: 'FieldAdd' }, { label: '変数', color: 'green', type: 'VariableAdd',editable:false },
{ label: '変数', color: 'green', type: 'VariableAdd', editable: false },
] ]
} }
}; };
}, },
}); });
</script> </script>
<style lang="scss"></style> <style lang="scss"></style>

View File

@@ -40,7 +40,7 @@
<div class="col-5"> <div class="col-5">
<ConditionObject v-model="item.field" /> <ConditionObject v-model="item.field" />
</div> </div>
<div class="col-2 q-pa-sm"> <div class="col-2">
<q-select v-model="item.logicalOperator" :options="logicalOperators" outlined dense></q-select> <q-select v-model="item.logicalOperator" :options="logicalOperators" outlined dense></q-select>
</div> </div>
<div class="col-4"> <div class="col-4">
@@ -78,8 +78,14 @@ type Props = {
type ProcessingObjectType = { type ProcessingObjectType = {
field?: { field?: {
sharedText: string; name: string | {
objectType: 'field'; name: string;
};
objectType: string;
type: string;
code: string;
label: string;
noLabel: boolean;
}; };
logicalOperator?: string; logicalOperator?: string;
vName?: string; vName?: string;
@@ -139,54 +145,34 @@ export default defineComponent({
const actionName = props.context.find(element => element?.props?.name === 'displayName') const actionName = props.context.find(element => element?.props?.name === 'displayName')
const processingProps: ValueType = props.modelValue && props.modelValue.vars const processingProps: ValueType = props.modelValue && props.modelValue.vars
? reactive(props.modelValue) ? props.modelValue
: reactive({ : reactive({
name: '', name: '',
actionName: actionName?.props?.modelValue as string, actionName: actionName?.props?.modelValue as string,
displayName: '結果(戻り値)', displayName: '結果(戻り値)',
vars: [ vars: [{ id: uuidv4() }]
{
id: uuidv4(),
field:{
objectType:'field',
sharedText:''
}
}]
}); });
const closeDg = () => { const closeDg = () => {
emit('update:modelValue', processingProps); emit('update:modelValue', processingProps
);
} }
const processingObjects = processingProps.vars; const processingObjects = processingProps.vars;
const deleteProcessingObject = (index: number) => { const deleteProcessingObject = (index: number) => processingObjects.length === 1
if(processingObjects.length >0){ ? processingObjects.splice(0, processingObjects.length, { id: uuidv4() })
processingObjects.splice(index, 1); : processingObjects.splice(index, 1);
}
if(processingObjects.length===0){
addProcessingObject();
}
}
const processingObjectsInputDisplay = computed(() => const processingObjectsInputDisplay = computed(() =>
processingObjects ? processingObjects ?
processingObjects processingObjects
.filter(item => item.field && item.logicalOperator && item.vName) .filter(item => item.field && item.logicalOperator && item.vName)
.map(item => { .map(item => {
return`var(${processingProps.name}.${item.vName}) = ${item.field?.sharedText}` return`var(${processingProps.name}.${item.vName}) = ${item.field.sharedText}`
}) })
: [] : []
); );
const addProcessingObject=()=>{
processingObjects.push({
id: uuidv4(),
field:{
objectType:'field',
sharedText:''
}
});
}
//集計処理方法 //集計処理方法
const logicalOperators = ref([ const logicalOperators = ref([
{ {
@@ -228,7 +214,7 @@ export default defineComponent({
closeDg, closeDg,
processingObjects, processingObjects,
processingProps, processingProps,
addProcessingObject, addProcessingObject: () => processingObjects.push({ id: uuidv4() }),
deleteProcessingObject, deleteProcessingObject,
logicalOperators, logicalOperators,
processingObjectsInputDisplay, processingObjectsInputDisplay,

View File

@@ -15,15 +15,8 @@
<q-icon name="search" class="cursor-pointer" color="primary" @click="showDg" /> <q-icon name="search" class="cursor-pointer" color="primary" @click="showDg" />
</template> </template>
</q-field> </q-field>
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeDg" min-width="400px"> <show-dialog v-model:visible="show" name="フィールド一覧" @close="closeDg" widht="400px">
<template v-slot:toolbar> <field-select ref="appDg" name="フィールド" :type="selectType" :appId="store.appInfo?.appId" :fieldTypes="fieldTypes"></field-select>
<q-input dense debounce="300" v-model="filter" placeholder="検索" clearable>
<template v-slot:before>
<q-icon name="search" />
</template>
</q-input>
</template>
<field-select ref="appDg" name="フィールド" :type="selectType" :appId="store.appInfo?.appId" :fieldTypes="fieldTypes" :filter="filter"></field-select>
</show-dialog> </show-dialog>
</div> </div>
</template> </template>
@@ -106,8 +99,7 @@ export default defineComponent({
showDg, showDg,
closeDg, closeDg,
selectedField, selectedField,
isSelected, isSelected
filter:ref(''),
}; };
} }
}); });

View File

@@ -1,50 +0,0 @@
export interface IApp {
id: string,
name: string
}
export interface IField {
label?:string;
code:string;
type?:string;
required?:boolean;
options?:string;
}
/**
* 選択されたフィールド
*/
export interface ISelectedField extends IField{
objectType:'Field'|'RefField';
}
export interface IAppFields {
app?: IApp,
name?:string;
fields: IField[]
}
/**
* 条件式の入力ボタンの属性定義
*/
export interface IButtonConfig{
label: string;
color: string;
type: 'FieldAdd' | 'VariableAdd' | 'FunctionAdd';
};
/**
* 条件入力項目の属性
*/
export interface IDynamicInputConfig{
canInput: boolean;
buttonsConfig: IButtonConfig[];
}
/**
* 条件式入力項目の属性
*/
export interface ICoditionConfig{
left:IDynamicInputConfig,
right:IDynamicInputConfig
}

View File

@@ -26,13 +26,15 @@
"sass": "^1.69.5", "sass": "^1.69.5",
"typescript": "^5.0.2", "typescript": "^5.0.2",
"vite": "^4.4.5", "vite": "^4.4.5",
"vite-plugin-checker": "^0.6.4" "vite-plugin-checker": "^0.6.4",
"vite-plugin-lib-inject-css": "^2.1.1"
}, },
"dependencies": { "dependencies": {
"@kintone/rest-api-client": "^5.5.2", "@kintone/rest-api-client": "^5.5.2",
"@popperjs/core": "^2.11.8", "@popperjs/core": "^2.11.8",
"@types/bootstrap": "^5.2.10", "@types/bootstrap": "^5.2.10",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"jquery": "^3.7.1" "jquery": "^3.7.1",
"vite-plugin-css-injected-by-js": "^3.5.1"
} }
} }

View File

@@ -0,0 +1,166 @@
import {
IAction,
IActionResult,
IActionNode,
IActionProperty,
IContext,
} from "../types/ActionTypes";
import { actionAddins } from ".";
interface Props {
displayName: string;
sources: Sources;
dataMapping: DataMapping[];
}
interface DataMapping {
id: string;
from: From;
to: To;
}
interface To {
app: App;
fields: Field[];
isDialogVisible: boolean;
}
interface Field {
name: string;
type: string;
code: string;
label: string;
noLabel: boolean;
required: boolean;
minLength: string;
maxLength: string;
expression: string;
hideExpression: boolean;
unique: boolean;
defaultValue: string;
}
interface From {
sharedText: string;
_t: string;
id: string;
objectType: string;
name: Name;
actionName: string;
displayName: string;
}
interface Name {
name: string;
}
interface Sources {
app: App;
}
interface App {
id: string;
name: string;
description: string;
createdate: string;
}
export class DataMappingAction implements IAction {
name: string;
actionProps: IActionProperty[];
dataMappingProps: Props;
constructor() {
this.name = "データマッピング";
this.actionProps = [];
this.dataMappingProps = {} as Props;
this.register();
}
async process(
prop: IActionNode,
event: any,
context: IContext
): Promise<IActionResult> {
this.actionProps = prop.actionProps;
this.dataMappingProps = prop.ActionValue as Props;
console.log(prop.ActionValue);
// this.initTypedActionProps();
let result = {
canNext: true,
result: "",
} as IActionResult;
try {
const record = this.dataMappingProps.dataMapping
.filter(
(item) =>
item.from.objectType === "variable" &&
item.from.name.name &&
item.to.app &&
item.to.fields &&
item.to.fields.length > 0
)
.reduce((accumulator, item) => {
return {...accumulator, [item.to.fields[0].code]: {
value: getValueByPath(context.variables, item.from.name.name),
}};
}, {});
if (record && Object.keys(record).length > 0) {
await kintone.api(kintone.api.url("/k/v1/record.json", true), "POST", {
app: this.dataMappingProps.sources.app.id,
record: record,
});
}
} catch (error) {
console.error("DataMappingAction error", error);
result.canNext = false;
}
console.log("dataMappingProps", this.dataMappingProps);
return result;
}
register(): void {
actionAddins[this.name] = this;
}
}
new DataMappingAction();
const getValueByPath = (obj: any, path: string) => {
return path.split(".").reduce((o, k) => (o || {})[k], obj);
};
type Resp = { records: RespRecordType[] };
type RespRecordType = {
[key: string]: {
type: string;
value: any;
};
};
type Result = {
type: string;
value: any[];
};
const selectData = async (appid: string, field: string): Promise<Result> => {
return kintone
.api(kintone.api.url("/k/v1/records", true), "GET", {
app: appid ?? kintone.app.getId(),
fields: [field],
})
.then((resp: Resp) => {
const result: Result = { type: "", value: [] };
resp.records.forEach((element) => {
for (const [key, value] of Object.entries(element)) {
if (result.type === "") {
result.type = value.type;
}
result.value.push(value.value);
}
});
return result;
});
};

View File

@@ -6,19 +6,67 @@ import {
IContext, IContext,
} from "../types/ActionTypes"; } from "../types/ActionTypes";
import { actionAddins } from "."; import { actionAddins } from ".";
import {KintoneRestAPIClient} from '@kintone/rest-api-client';
import { Aggregator,Operator} from '../util/aggregates';
import { FieldForm } from "../types/FieldLayout";
interface IDataProcessingProps { interface Props {
displayName: string; displayName: string;
sources: Sources; sources: Sources;
condition: string; condition: string;
verName?: VerName; conditionO: Condition;
verName: VerName;
} }
interface Condition { interface Condition {
queryString: string; queryString: string;
index: number;
type: string;
children: Child[];
parent: null;
logicalOperator: string;
}
interface Child {
index: number;
type: string;
parent: string;
object: Object;
operator: ChildOperator;
value: Value;
}
interface Value {
sharedText: string;
_t: string;
objectType: string;
actionName: string;
displayName: string;
name: Name;
}
interface Name {
name: string;
}
interface ChildOperator {
label: string;
value: string;
}
interface Object {
sharedText: string;
_t: string;
name: string;
objectType: string;
type: string;
code: string;
label: string;
noLabel: boolean;
required: boolean;
minLength: string;
maxLength: string;
expression: string;
hideExpression: boolean;
unique: boolean;
defaultValue: string;
} }
interface VerName { interface VerName {
@@ -30,55 +78,69 @@ interface VerName {
interface Var { interface Var {
id: string; id: string;
field: FieldForm; field: Field2;
logicalOperator: CalcOperator; logicalOperator: LogicalOperator;
vName: string; vName: string;
} }
interface CalcOperator { interface LogicalOperator {
operator: Operator; operator: string;
label: string; label: string;
} }
interface Field2 {
sharedText: string;
_t: string;
name: string;
objectType: string;
type: string;
code: string;
label: string;
noLabel: boolean;
required: boolean;
minLength: string;
maxLength: string;
expression: string;
hideExpression: boolean;
unique: boolean;
defaultValue: string;
}
interface Sources { interface Sources {
app: App; app: App;
fields: FieldForm[]; fields: Field[];
}
interface Field {
name: string;
type: string;
code: string;
label: string;
noLabel: boolean;
required: boolean;
minLength: string;
maxLength: string;
expression: string;
hideExpression: boolean;
unique: boolean;
defaultValue: string;
} }
interface App { interface App {
id: string; id: string;
name?: string; name: string;
description: string;
createdate: string;
} }
type Result = {
[key: string]: {
type: string;
value: any[];
};
};
type AnyObject = {
[key: string]: any;
};
export class DataProcessingAction implements IAction { export class DataProcessingAction implements IAction {
name: string; name: string;
actionProps: IActionProperty[]; actionProps: IActionProperty[];
props: IDataProcessingProps ; dataProcessingProps: Props | null;
constructor() { constructor() {
this.name = "データ処理"; this.name = "データ処理";
this.actionProps = []; this.actionProps = [];
this.props = { this.dataProcessingProps = null;
displayName:'',
condition:'',
sources:{
app:{
id:""
},
fields:[]
},
};
this.register(); this.register();
} }
@@ -88,55 +150,55 @@ export class DataProcessingAction implements IAction {
context: IContext context: IContext
): Promise<IActionResult> { ): Promise<IActionResult> {
this.actionProps = nodes.actionProps; this.actionProps = nodes.actionProps;
this.dataProcessingProps = nodes.ActionValue as Props;
this.props = nodes.ActionValue as IDataProcessingProps; this.dataProcessingProps.conditionO = JSON.parse(
const condition = JSON.parse(this.props.condition) as Condition; this.dataProcessingProps.condition
);
let result = { let result = {
canNext: true, canNext: true,
result: "", result: "",
} as IActionResult; } as IActionResult;
try { try {
if (!this.props) { if (!this.dataProcessingProps) {
return result; return result;
} }
const query = this.getQuery(condition.queryString,context.variables); const data = await selectData(
const data = await this.selectData(query); varGet(
this.dataProcessingProps.conditionO.queryString,
context.variables
)
);
console.log("data ", data); console.log("data ", data);
if(this.props.verName){ context.variables[this.dataProcessingProps.verName.name] =
const varValues= this.props.verName.vars.reduce((acc, f) => { this.dataProcessingProps.verName.vars.reduce((acc, f) => {
const datas=data[f.field.code].value; const v = calc(f, data);
const agg = new Aggregator(datas,f.field); if (v) {
const result = agg.calculate(f.logicalOperator.operator) acc[f.vName] = calc(f, data);
acc[f.vName]=result; }
return acc; return acc;
}, {} as AnyObject); }, {} as AnyObject);
context.variables[this.props.verName.name]=varValues;
console.log("context ", context); console.log("context ", context);
}
return result; return result;
} catch (error) { } catch (error) {
console.error("データ集計中例外が発生しました。", error); console.error(error);
if(error instanceof Error){ event.error = error;
event.error = `データ集計中例外が発生しました。 ${error.message}`;
}else{
event.error = "データ集計中例外が発生しました。";
}
result.canNext = false;
return result; return result;
} }
} }
/** register(): void {
* actionAddins[this.name] = this;
* @param str }
* @param vars }
* @returns
*/ new DataProcessingAction();
getQuery = (str: string, vars: any) => {
const varGet = (str: string, vars: any) => {
console.log(str); console.log(str);
const regex = /var\((.*?)\)/g; const regex = /var\((.*?)\)/g;
let match; let match;
while ((match = regex.exec(str)) !== null) { while ((match = regex.exec(str)) !== null) {
@@ -149,23 +211,17 @@ export class DataProcessingAction implements IAction {
} }
console.log(str); console.log(str);
return str; return str;
}; };
/** const selectData = async (query?: string) => {
* データを取得する return kintone
* @param query .api(kintone.api.url("/k/v1/records", true), "GET", {
* @returns app: kintone.app.getId(),
*/ query: query,
selectData = async ( query?: string) => { })
const api = new KintoneRestAPIClient(); .then((resp: Resp) => {
const fields = this.props.sources.fields.map((field)=>field.code);
const resp = await api.record.getAllRecords({
app: this.props.sources.app.id,
fields:fields,
condition:query
});
const result: Result = {}; const result: Result = {};
resp.forEach((element) => { resp.records.forEach((element) => {
for (const [key, value] of Object.entries(element)) { for (const [key, value] of Object.entries(element)) {
if (!result[key]) { if (!result[key]) {
result[key] = { type: value.type, value: [] }; result[key] = { type: value.type, value: [] };
@@ -174,12 +230,145 @@ export class DataProcessingAction implements IAction {
} }
}); });
return result; return result;
});
};
type Resp = { records: RespRecordType[] };
type RespRecordType = {
[key: string]: {
type: string;
value: any;
}; };
};
register(): void { type Result = {
actionAddins[this.name] = this; [key: string]: {
type: string;
value: any[];
};
};
type AnyObject = {
[key: string]: any;
};
const ERROR_TYPE = "ERROR_TYPE";
const calc = (f: Var, result: Result) => {
const type = typeCheck(f.field.type);
if (!type) {
return ERROR_TYPE;
} }
const fun =
calcFunc[
`${type}_${Operator[f.logicalOperator.operator as keyof typeof Operator]}`
];
if (!fun) {
return ERROR_TYPE;
}
const values = result[f.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 "DATE":
return CalcType.DATE;
case "TIME":
return CalcType.TIME;
case "DATETIME":
case "UPDATED_TIME":
return CalcType.DATETIME;
default:
return null;
}
};
enum Operator {
SUM = "SUM",
AVG = "AVG",
MAX = "MAX",
MIN = "MIN",
COUNT = "COUNT",
FIRST = "FIRST",
} }
new DataProcessingAction(); 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
),
[`${CalcType.STRING}_${Operator.FIRST}`]: (value: string[]) => {
return value[0];
},
};

View File

@@ -1,334 +0,0 @@
import {
IAction,
IActionResult,
IActionNode,
IActionProperty,
IContext,
} from "../types/ActionTypes";
import { actionAddins } from ".";
import { KintoneRestAPIClient } from "@kintone/rest-api-client";
import { Lookup } from "@kintone/rest-api-client/lib/src/KintoneFields/types/property";
import { FieldForm, FieldType } from "../types/FieldLayout";
interface Props {
displayName: string;
sources: Sources;
dataMapping: DataMapping;
}
interface DataMapping {
data: Mapping[];
createWithNull: boolean;
}
interface Mapping {
id: string;
from: From;
to: To;
isKey: boolean;
}
interface To {
app: App;
fields:FieldForm[];
isDialogVisible: boolean;
}
interface From {
sharedText: string;
id: string;
objectType: 'variable'|'field'|'text';
}
interface IVar extends From{
name:{
name:string;
}
}
interface IFromField extends From,FieldForm{
}
interface Sources {
app: App;
}
interface App {
id: string;
name: string;
description: string;
createdate: string;
}
export class DataUpdateAction implements IAction {
name: string;
actionProps: IActionProperty[];
dataMappingProps: Props;
constructor() {
this.name = "データ更新";
this.actionProps = [];
this.dataMappingProps = {} as Props;
this.register();
}
async process(
prop: IActionNode,
event: any,
context: IContext
): Promise<IActionResult> {
this.actionProps = prop.actionProps;
this.dataMappingProps = prop.ActionValue as Props;
console.log(context);
let result = {
canNext: true,
result: "",
} as IActionResult;
try {
const lookupFixedFieldCodes = await getLookupFixedFieldCodes(
this.dataMappingProps.sources.app.id
);
// createWithNull が有効な場合は、4 番目のパラメーターを true にして doUpdate 関数ブランチを実行します。
if (this.dataMappingProps.dataMapping.createWithNull) {
await doUpdate(
this.dataMappingProps.dataMapping.data,
this.dataMappingProps.sources.app.id,
context,
true, // キーがない場合、またはキーでターゲットが見つからない場合に、マッピング条件によって新しいレコードを作成するかどうかを決定するために使用されます。
lookupFixedFieldCodes
);
} else if (
// キーがないと更新対象を取得できないため、この時点でのみ更新が行われます。 doUpdate 関数の 4 番目のパラメーターは false です。
this.dataMappingProps.dataMapping.data
.map((m) => m.isKey)
.find((isKey) => isKey === true)
) {
await doUpdate(
this.dataMappingProps.dataMapping.data,
this.dataMappingProps.sources.app.id,
context,
false,
lookupFixedFieldCodes
);
} else {
await doCreate(
this.dataMappingProps.dataMapping.data,
this.dataMappingProps.sources.app.id,
context,
lookupFixedFieldCodes
);
}
} catch (error) {
console.error("DataMappingAction error", error);
result.canNext = false;
}
console.log("dataMappingProps", this.dataMappingProps);
return result;
}
register(): void {
actionAddins[this.name] = this;
}
}
new DataUpdateAction();
const getContextVarByPath = (obj: any, path: string) => {
return path.split(".").reduce((o, k) => (o || {})[k], obj);
};
interface UpdateRecord {
id: string;
record: {
[key: string]: {
value: any;
};
};
}
const client = new KintoneRestAPIClient();
const getFromValue=(item:Mapping,context:IContext)=>{
if (item.from.objectType === "variable") {
const rfrom =item.from as IVar;
return getContextVarByPath(context.variables,rfrom.name.name);
}else if(item.from.objectType === "field"){
const field = item.from as IFromField;
return context.record[field.code].value;
}
else {
return item.from.sharedText;
}
}
const doUpdate = async (
mappingData: Mapping[],
appId: string,
context: IContext,
needCreate: boolean,
lookupFixedFieldCodes: string[]
) => {
const targetField = await findUpdateField(mappingData, appId, context);
console.log(targetField);
if (targetField.records.length === 0 && needCreate) {
await doCreate(mappingData, appId, context, lookupFixedFieldCodes);
} else {
// マッピングデータを単純なオブジェクトに処理し、ソース値が変数の場合は変数を置き換えます。
const mappingRules = mappingData
.filter(
(m) =>
Object.keys(m.from).length > 0 &&
!lookupFixedFieldCodes.includes(m.to.fields[0].code)
)
.map((m) => {
if (m.from.objectType === "variable") {
const rfrom =m.from as IVar;
return {
value: getContextVarByPath(context.variables,rfrom.name.name),
code: m.to.fields[0].code,
};
}else if(m.from.objectType === "field"){
const field = m.from as IFromField;
return {
value: context.record[field.code].value,
code: m.to.fields[0].code,
}
}
else {
return {
value: m.from.sharedText,
code: m.to.fields[0].code,
};
}
});
const updateRecords: UpdateRecord[] = targetField.records.map(
(targetRecord) => {
const updateRecord: UpdateRecord["record"] = {};
// マッピング内のルールにヒットしたフィールドのみが更新されます。
for (const mapping of mappingRules) {
if (targetRecord[mapping.code]) {
updateRecord[mapping.code] = {
value: mapping.value,
};
}
}
return {
id: targetRecord.$id.value as string,
record: updateRecord,
};
}
);
console.log(updateRecords);
await client.record.updateRecords({
app: appId,
records: updateRecords,
});
}
};
const makeQuery=(field:FieldForm,key:any)=>{
if(field.type===FieldType.NUMBER || field.type===FieldType.RECORD_NUMBER){
return `${field.code} = ${Number(key)}`
}
if(typeof key==='string'){
return `${field.code} = "${key}"`
}
}
const findUpdateField = async (
mappingData: Mapping[],
appId: string,
context: IContext
) => {
const queryStr = mappingData
.filter((m) => m.to.app && m.to.fields && m.to.fields.length > 0 && m.isKey)
.map((m) => {
if (m.from.objectType === "variable") {
const vfrom = m.from as IVar;
return makeQuery(m.to.fields[0],getContextVarByPath(context.variables , vfrom.name.name));
}
else if(m.from.objectType === "field"){
const field = m.from as IFromField;
return makeQuery(m.to.fields[0],context.record[field.code].value);
}
else{
return makeQuery(m.to.fields[0],m.from.sharedText);
}
})
.join("&");
// 検索条件が空の場合は全レコードを返すため、検索対象が見つからない場合は検索は行われません。
if (queryStr.length === 0) {
return {
records: [],
};
} else {
return await client.record.getRecords({
app: appId,
// query: undefined
query: queryStr,
});
}
};
const doCreate = async (
mappingData: Mapping[],
appId: string,
context: IContext,
lookupFixedFieldCodes: string[]
) => {
const filterHandler = (item:Mapping)=>{
if(!item.to.fields || item.to.fields.length===0){
return false;
}
if(item.from.objectType === "variable" && (item.from as IVar).name.name ){
return true;
}
if(item.from.objectType === "field" && (item.from as IFromField).code){
return true;
}
if(item.from.objectType === "text" && item.from.sharedText!==null){
return true;
}
return false;
}
const record = mappingData
.filter(filterHandler)
.filter((item) => !lookupFixedFieldCodes.includes(item.to.fields[0].code))
.reduce((accumulator, item) => {
return {
...accumulator,
[item.to.fields[0].code]: {
value: getFromValue(item,context),
},
};
}, {});
if (record && Object.keys(record).length > 0) {
console.log(record);
await client.record.addRecord({
app:appId,
record:record
});
// await kintone.api(kintone.api.url("/k/v1/record.json", true), "POST", {
// app: appId,
// record: record,
// });
}
};
const getLookupFixedFieldCodes = async (appId: string) => {
return await client.app
.getFormFields({ app: appId })
.then((resp) =>
Object.values(resp.properties)
.filter((f) => (f as Lookup).lookup !== undefined)
.flatMap((f) => (f as Lookup).lookup.fieldMappings.map((m) => m.field))
);
};

View File

@@ -88,8 +88,7 @@ export class InsertValueAction implements IAction{
let singleDigitMonthDay = inputValue.match(/(\d{4})-(\d{1})-(\d{1})$/);//4桁の数字-1桁の数字-2桁の数字 let singleDigitMonthDay = inputValue.match(/(\d{4})-(\d{1})-(\d{1})$/);//4桁の数字-1桁の数字-2桁の数字
let singleDigitMonth = inputValue.match(/(\d{4})-(\d{1})-(\d{2})$/);//4桁の数字-1桁の数字-2桁の数字 let singleDigitMonth = inputValue.match(/(\d{4})-(\d{1})-(\d{2})$/);//4桁の数字-1桁の数字-2桁の数字
let singleDigitDay = inputValue.match(/(\d{4})-(\d{2})-(\d{1})$/);//4桁の数字-2桁の数字-1桁の数字 let singleDigitDay = inputValue.match(/(\d{4})-(\d{2})-(\d{1})$/);//4桁の数字-2桁の数字-1桁の数字
let dateTimeMilliSecond = inputValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).(\d{2,3})Z$/);//時刻入りのUTCの日付形式(ミリ秒) let dateTime = inputValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).000Z/);//時刻入りのUTCの日付形式
let dateTime = inputValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/);//時刻入りのUTCの日付形式
let date; let date;
//date型に変換 //date型に変換
date = new Date(inputValue); date = new Date(inputValue);
@@ -97,7 +96,7 @@ export class InsertValueAction implements IAction{
//date型変換できたか確認 //date型変換できたか確認
if(date !== undefined && !isNaN(date.getDate())){ if(date !== undefined && !isNaN(date.getDate())){
//正規表現チェック確認 //正規表現チェック確認
if(twoDigitMonthDay === null && singleDigitMonth === null && singleDigitDay === null && singleDigitMonthDay === null && dateTime === null && dateTimeMilliSecond === null){ if(twoDigitMonthDay === null && singleDigitMonth === null && singleDigitDay === null && singleDigitMonthDay === null && dateTime === null){
event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。"; //レコードにエラーを表示 event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。"; //レコードにエラーを表示
throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。「値を挿入する」コンポーネントの処理を中断しました。"); throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。「値を挿入する」コンポーネントの処理を中断しました。");
} }
@@ -441,9 +440,6 @@ export class InsertValueAction implements IAction{
} }
} }
//保存成功イベントの場合、kintone async/await による非同期処理でフィールドに値を挿入する
if(!event.type.includes('success')){
//条件式の結果がtrueかつ挿入する値が変換できた場合、フィールドラジオボタン・ドロップダウン・チェックボックス・複数選択・文字列一行・文字列複数行・リッチエディタ・数値・日付・日時・時刻にセット //条件式の結果がtrueかつ挿入する値が変換できた場合、フィールドラジオボタン・ドロップダウン・チェックボックス・複数選択・文字列一行・文字列複数行・リッチエディタ・数値・日付・日時・時刻にセット
if(conditionResult && (correctFormattedValue || correctValues)){ if(conditionResult && (correctFormattedValue || correctValues)){
//条件式の結果がtureかつ、値を正しい形式に変換できた場合、フィールドに値をセットする //条件式の結果がtureかつ、値を正しい形式に変換できた場合、フィールドに値をセットする
@@ -455,38 +451,6 @@ export class InsertValueAction implements IAction{
} }
} }
}else{
//kintone async/await による非同期処理(保存成功時イベントREST API処理時)
async function updateRecord(fieldCode:string,event:any,insertValue:any) {
return new Promise((resolve, reject) => {
var updatedRecord = {
app: event.appId,
id: event.recordId,
record: {[fieldCode]:{"value":insertValue}}
};
kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', updatedRecord, (resp) => {
resolve(resp);
}, (error) => {
reject(error);
});
});
}
//条件式の結果がtrueかつ挿入する値が変換できた場合、フィールドラジオボタン・ドロップダウン・チェックボックス・複数選択・文字列一行・文字列複数行・リッチエディタ・数値・日付・日時・時刻にセット
if(conditionResult && (correctFormattedValue || correctValues)){
//条件式の結果がtureかつ、値を正しい形式に変換できた場合、フィールドに値をセットする
if(correctFormattedValue){
event.record[fieldCode].value = correctFormattedValue;
//条件式の結果がtureかつ、値を正しい形式配列に変換できた場合、フィールドに値配列をセットする
}else if(correctValues.length > 0){
event.record[fieldCode].value = correctValues;
}
}
//kintone async/await による非同期処理(レコード更新)
await updateRecord(fieldCode,event,correctFormattedValue);
};
result= { result= {
canNext:true, canNext:true,
result:true result:true

View File

@@ -51,19 +51,13 @@ export class MailCheckAction implements IAction {
const value = record[this.props.field.code].value; const value = record[this.props.field.code].value;
if (this.props.emailCheck === '厳格') { if (this.props.emailCheck === '厳格') {
if (!/^[a-zA-Z0-9_-¥.]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value)) { if (!/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value)) {
record[this.props.field.code].error = this.props.message; record[this.props.field.code].error = this.props.message;
} }
else {
record[this.props.field.code].error = null;
}
} else if (this.props.emailCheck === 'ゆるめ') { } else if (this.props.emailCheck === 'ゆるめ') {
if (!/^[^@]+@[^@]+$/.test(value)) { if (!/^[^@]+@[^@]+$/.test(value)) {
record[this.props.field.code].error = this.props.message; record[this.props.field.code].error = this.props.message;
} }
else {
record[this.props.field.code].error = null;
}
} else { } else {
result = { result = {
canNext: true, canNext: true,

View File

@@ -159,32 +159,32 @@ export class StringJoinAction implements IAction{
if (!event.type.includes('success')){ if (!event.type.includes('success')){
//保存先フィールドに値セット: //保存先フィールドに値セット:
record[this.props.saveField.code].value=saveValue; record[this.props.saveField.code].value=saveValue;
//window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。"); window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。");
}else{ }else{
//kintone async/await による非同期処理(成功イベントREST API処理時) const params={
async function updateRecord(fieldCode:string,event:any) { "app":event.appId,
return new Promise((resolve, reject) => { "id":event.recordId,
var updatedRecord = { "record":{[this.props.saveField.code]:{"value":saveValue}}
app: event.appId,
id: event.recordId,
record: {[fieldCode]:{"value":saveValue}}
}; };
kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', updatedRecord, (resp) => { return await kintone.api(kintone.api.url('/k/v1/record',true),'PUT',params).then((resp) => {
resolve(resp);
}, (error) => {
reject(error);
});
});
}
//kintone保存先フィールド存在確認 //kintone保存先フィールド存在確認
record[this.props.saveField.code].value=saveValue; record[this.props.saveField.code].value=saveValue;
//kintone async/await による非同期処理:
await updateRecord(this.props.saveField.code,event);
//一覧画面更新成功後手動リロードください:
if (event.type.includes('index')){ if (event.type.includes('index')){
//window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。一覧画面更新成功後自動リロードしません。必要に応じて手動リロードください。"); window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。一覧画面更新成功後自動リロードしません。必要に応じて手動リロードください。");
window.alert("文字結合には、一覧画面更新成功後自動リロードしません。必要に応じて手動リロードください。"); }else{
window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。");
} }
//一覧画面更新成功後リロード:
// if (event.type.includes('index')){
// event.url = location.href.endsWith('/') || location.href.endsWith('&') ?
// location.href.slice(0, -1) :
// location.href + (location.href.includes('?') ? '&' : '/');
// }
}).catch((error) => {
event.error = 'エラーが発生しました。結合しません。システム管理者へお問合せください';
window.alert(event.error+"error message"+error);
return event;
});
} }
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////
result= { result= {

View File

@@ -1,10 +1,12 @@
import { actionAddins } from "."; import { actionAddins } from ".";
import { IAction,IActionResult, IActionNode, IActionProperty, IField, IContext } from "../types/ActionTypes"; import { IAction,IActionResult, IActionNode, IActionProperty, IField, IContext } from "../types/ActionTypes";
//クラス名を設計書に揃える
/** /**
* アクションの属性定義 * アクションの属性定義
*/ */
interface FullWidthProps{ interface FullWidthProps{
//checkOption:Array<string>,
field:IField field:IField
} }
/** /**
@@ -18,6 +20,7 @@ export class FullWidthAction implements IAction{
this.name="全角チェック"; /* pgadminのnameと同様 */ this.name="全角チェック"; /* pgadminのnameと同様 */
this.actionProps=[]; this.actionProps=[];
this.props={ this.props={
//checkOption:[],
field:{code:''} field:{code:''}
} }
//アクションを登録する //アクションを登録する
@@ -47,17 +50,15 @@ export class FullWidthAction implements IAction{
//条件分岐 //条件分岐
//未入力時は何も処理をせず終了 //未入力時は何も処理をせず終了
if(value===undefined || value===''){ if(value===undefined || value===''){
record[this.props.field.code].error=null; return result;
} }
//半角が含まれていた場合resultがfalse //半角が含まれていた場合resultがfalse
if(!this.containsFullWidthChars(value) && !(value === undefined || value ==='')){ if(!this.containsFullWidthChars(value)){
//エラー時に出力される文字設定 //エラー時に出力される文字設定
record[this.props.field.code].error="半角が含まれています"; record[this.props.field.code].error="半角が含まれています";
//次の処理を中止する値設定 //次の処理を中止する値設定
result.canNext=false; result.canNext=false;
} return result;
else{
record[this.props.field.code].error=null;
} }
//resultプロパティ指定 //resultプロパティ指定
result= { result= {
@@ -78,7 +79,6 @@ export class FullWidthAction implements IAction{
containsFullWidthChars(text: string): boolean { containsFullWidthChars(text: string): boolean {
// 半角英数字カナ記号を除外 // 半角英数字カナ記号を除外
//全角かどうか
const checkRegex="^[^\x01-\x7E\uFF61-\uFF9F]+$"; const checkRegex="^[^\x01-\x7E\uFF61-\uFF9F]+$";
//正規表現オブジェクト生成 //正規表現オブジェクト生成

View File

@@ -47,7 +47,7 @@ export class HalfWidthAction implements IAction{
//条件分岐 //条件分岐
//未入力時は何も処理をせず終了 //未入力時は何も処理をせず終了
if(value===undefined || value===''){ if(value===undefined || value===''){
record[this.props.field.code].error=null; return result;
} }
//全角が含まれていた場合保存処理中止(エラー処理) //全角が含まれていた場合保存処理中止(エラー処理)
if(!this.containsHalfWidthChars(value)){ if(!this.containsHalfWidthChars(value)){
@@ -55,9 +55,7 @@ export class HalfWidthAction implements IAction{
record[this.props.field.code].error="全角が含まれています"; record[this.props.field.code].error="全角が含まれています";
//次の処理を中止する値設定 //次の処理を中止する値設定
result.canNext=false; result.canNext=false;
} return result;
else{
record[this.props.field.code].error=null;
} }
//半角の場合問題なく実行 //半角の場合問題なく実行
//resultプロパティ指定 //resultプロパティ指定

View File

@@ -42,12 +42,7 @@ $(function (){
const flow=ActionFlow.fromJSON(flowinfo.content); const flow=ActionFlow.fromJSON(flowinfo.content);
if(flow!==undefined){ if(flow!==undefined){
const process = new ActionProcess(event.type,flow,event); const process = new ActionProcess(event.type,flow,event);
process.exec().then((res)=>{ process.exec();
const record = event.record;
kintone.app.record.set({record});
}).catch((err)=>{
console.error(err);
});
} }
return event; return event;
}); });
@@ -63,7 +58,7 @@ $(function (){
await process.exec(); await process.exec();
} }
const record = event.record; const record = event.record;
kintone.app.record.set({record}); kintone.app.record.set({record})
}); });
}); });
} }

View File

@@ -347,9 +347,6 @@ export class ConditionTree {
if(!object || typeof object!=="object"){ if(!object || typeof object!=="object"){
return object; return object;
} }
if("sharedText" in object){
return object.sharedText;
}
if("label" in object){ if("label" in object){
return object.label; return object.label;
} }

View File

@@ -1,240 +0,0 @@
// src/types/field.d.ts
export enum FieldType {
CALC = "CALC",
CATEGORY = "CATEGORY",
CHECK_BOX = "CHECK_BOX",
CREATED_TIME = "CREATED_TIME",
CREATOR = "CREATOR",
DATE = "DATE",
DATETIME = "DATETIME",
DROP_DOWN = "DROP_DOWN",
FILE = "FILE",
GROUP = "GROUP",
GROUP_SELECT = "GROUP_SELECT",
LINK = "LINK",
MODIFIER = "MODIFIER",
MULTI_LINE_TEXT = "MULTI_LINE_TEXT",
MULTI_SELECT = "MULTI_SELECT",
NUMBER = "NUMBER",
ORGANIZATION_SELECT = "ORGANIZATION_SELECT",
RADIO_BUTTON = "RADIO_BUTTON",
RECORD_NUMBER = "RECORD_NUMBER",
REFERENCE_TABLE = "REFERENCE_TABLE",
RICH_TEXT = "RICH_TEXT",
SINGLE_LINE_TEXT = "SINGLE_LINE_TEXT",
STATUS = "STATUS",
STATUS_ASSIGNEE = "STATUS_ASSIGNEE",
SUBTABLE = "SUBTABLE",
TIME = "TIME",
UPDATED_TIME = "UPDATED_TIME",
USER_SELECT = "USER_SELECT"
}
export enum CalcFormat{
NUMBER = "NUMBER",
NUMBER_DIGIT = "NUMBER_DIGIT",
DATETIME = "DATETIME",
DATE = "DATE",
TIME = "TIME",
HOUR_MINUTE= "HOUR_MINUTE",
DAY_HOUR_MINUTE= "DAY_HOUR_MINUTE"
}
export interface FieldForm {
code: string;
type: FieldType;
required?: boolean;
noLabel?: boolean;
}
export interface OptionForm{
index: string;
label: string;
}
export interface EntityForm {
code: string;
type: 'USER' | 'ORGANIZATION' | 'GROUP' | 'FUNCTION';
}
export interface CalcFieldForm extends FieldForm {
unit?: string;
expression?: string;
format?:CalcFormat;
unitPosition?: 'BEFORE' | 'AFTER';
displayScale?: string;
hideExpression?: boolean;
}
export interface CategoryFieldForm extends FieldForm {
enabled?: boolean;
}
export interface DateFieldForm extends FieldForm {
defaultValue?: string;
unique?: boolean;
defaultNowValue?: boolean;
}
export interface DatetimeFieldForm extends FieldForm {
defaultValue?: string;
unique?: boolean;
defaultNowValue?: boolean;
}
export interface DecimalFieldForm extends FieldForm {
maxValue?: string;
defaultValue?: string;
unitPosition?: 'BEFORE' | 'AFTER';
minValue?: string;
unit?: string;
unique?: boolean;
displayScale?: string;
digit?: boolean;
}
export interface EditorFieldForm extends FieldForm {
defaultValue?: string;
}
export interface EntityForm {
code: string;
type: 'USER' | 'ORGANIZATION' | 'GROUP' | 'FUNCTION';
}
export interface FieldMappingForm {
relatedField: string;
field: string;
}
export interface FileFieldForm extends FieldForm {
thumbnailSize?: string;
}
export interface GroupFieldForm extends FieldForm {
openGroup?: boolean;
}
export interface GroupSelectFieldForm extends FieldForm {
entities: EntityForm[];
defaultValue?: EntityForm[];
}
export interface LinkFieldForm extends FieldForm {
protocol?: 'WEB' | 'CALL' | 'MAIL';
defaultValue?: string;
minLength?: string;
unique?: boolean;
maxLength?: string;
}
export interface LookupFieldForm extends FieldForm {
lookup: {
lookupPickerFields: string[];
relatedKeyField: string;
relatedApp: {
app: string;
code: string;
};
fieldMappings: FieldMappingForm[];
sort?: string;
filterCond?: string;
};
}
export interface ModifiedAtFieldForm extends FieldForm {}
export interface ModifierFieldForm extends FieldForm {}
export interface MultipleCheckFieldForm extends FieldForm {
defaultValue?: string[];
options: {
[key: string]: OptionForm;
};
align?: 'HORIZONTAL' | 'VERTICAL';
}
export interface MultipleLineTextFieldForm extends FieldForm {
defaultValue?: string;
}
export interface MultipleSelectFieldForm extends FieldForm {
defaultValue?: string[];
options: {
[key: string]: OptionForm;
};
}
export interface OrganizationSelectFieldForm extends FieldForm {
entities: EntityForm[];
defaultValue?: EntityForm[];
}
export interface RecordIdFieldForm extends FieldForm {}
export interface ReferenceTableFieldForm extends FieldForm {
referenceTable: {
condition: {
relatedField: string;
field: string;
};
size?: string;
relatedApp: {
app: string;
code: string;
};
sort?: string;
filterCond?: string;
displayFields: string[];
};
}
export interface SingleCheckFieldForm extends FieldForm {
defaultValue?: string;
options: {
[key: string]: OptionForm;
};
align?: 'HORIZONTAL' | 'VERTICAL';
}
export interface SingleLineTextFieldForm extends FieldForm {
expression?: string;
defaultValue?: string;
minLength?: string;
unique?: boolean;
maxLength?: string;
hideExpression?: boolean;
}
export interface SingleSelectFieldForm extends FieldForm {
defaultValue?: string;
options: {
[key: string]: OptionForm;
};
}
export interface StatusAssigneeFieldForm extends FieldForm {
enabled?: boolean;
}
export interface StatusFieldForm extends FieldForm {
enabled?: boolean;
}
export interface TableForm extends FieldForm {
fields: {
[key: string]: CalcFieldForm | CategoryFieldForm | DateFieldForm | DatetimeFieldForm | DecimalFieldForm | EditorFieldForm | FileFieldForm | GroupFieldForm | GroupSelectFieldForm | LinkFieldForm | LookupFieldForm | ModifiedAtFieldForm | ModifierFieldForm | MultipleCheckFieldForm | MultipleLineTextFieldForm | MultipleSelectFieldForm | OrganizationSelectFieldForm | RecordIdFieldForm | ReferenceTableFieldForm | SingleCheckFieldForm | SingleLineTextFieldForm | SingleSelectFieldForm | StatusAssigneeFieldForm | StatusFieldForm | TableForm | TimeFieldForm | UserSelectFieldForm;
};
}
export interface TimeFieldForm extends FieldForm {
defaultValue?: string;
defaultNowValue?: boolean;
}
export interface UserSelectFieldForm extends FieldForm {
entities: EntityForm[];
defaultValue?: EntityForm[];
}

View File

@@ -7,7 +7,7 @@ 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 '../actions/data-processing';
import '../actions/data-update'; import '../actions/data-mapping';
import '../actions/current-field-get'; import '../actions/current-field-get';
import '../actions/regular-check'; import '../actions/regular-check';
import '../actions/mail-check'; import '../actions/mail-check';

View File

@@ -1,121 +0,0 @@
import { FieldForm,CalcFieldForm,FieldType, CalcFormat} from "../types/FieldLayout";
/**
* 集計操作子
*/
export enum Operator {
SUM = "SUM",
AVG = "AVG",
MAX = "MAX",
MIN = "MIN",
COUNT = "COUNT",
FIRST = "FIRST",
LAST = "LAST"
}
/**
* 集計関数
*/
export class Aggregator {
private data: string[];
private field: FieldForm;
constructor(data: string[], field: FieldForm) {
this.data = data;
this.field = field;
}
private toNumberArray(): number[] {
const numberArray = this.data.map(item => {
const num = Number(item);
if (isNaN(num)) {
throw new Error(`フィールド「${this.field.code} 」は数値に変換できないため、計算を実行できません。`);
}
return num;
});
return numberArray;
}
private sum(): number | null {
if (this.data.length === 0) return null;
const numberArray = this.toNumberArray();
return numberArray.reduce((acc, val) => acc + val, 0);
}
private avg(): number | null {
if (this.data.length === 0) return null;
const numberArray = this.toNumberArray();
const total = numberArray.reduce((acc, val) => acc + val, 0);
return total / numberArray.length;
}
private max(): number | string | null {
if (this.data.length === 0) return null;
if (this.field.type === FieldType.NUMBER ) {
const numberArray = this.toNumberArray();
return Math.max(...numberArray);
}
if(this.field.type===FieldType.CALC){
const calcField = this.field as CalcFieldForm;
if(calcField.format===CalcFormat.NUMBER || calcField.format===CalcFormat.NUMBER_DIGIT){
const numberArray = this.toNumberArray();
return Math.max(...numberArray);
}
}
return this.data.reduce((max, item) => (item > max ? item : max), this.data[0]);
}
private min(): number | string | null {
if (this.data.length === 0) return null;
if (this.field.type === FieldType.NUMBER ) {
const numberArray = this.toNumberArray();
return Math.min(...numberArray);
}
if(this.field.type===FieldType.CALC){
const calcField = this.field as CalcFieldForm;
if(calcField.format===CalcFormat.NUMBER || calcField.format===CalcFormat.NUMBER_DIGIT){
const numberArray = this.toNumberArray();
return Math.min(...numberArray);
}
}
if(this.data===null || this.data.length===0){
return null;
}
return this.data.reduce((min, item) => (item < min ? item : min), this.data[0]);
}
private count(): number {
return this.data.length;
}
private first(): string | null {
return this.data.length ? this.data[0] : null;
}
private last(): string | null {
return this.data.length ? this.data[this.data.length - 1] : null;
}
public calculate(operator: Operator): number | string | null {
switch (operator) {
case Operator.SUM:
return this.sum();
case Operator.AVG:
return this.avg();
case Operator.MAX:
return this.max();
case Operator.MIN:
return this.min();
case Operator.COUNT:
return this.count();
case Operator.FIRST:
return this.first();
case Operator.LAST:
return this.last();
default:
return null;
}
}
}

View File

@@ -1,7 +1,7 @@
// vite.config.js // vite.config.js
import { defineConfig, loadEnv } from "vite"; import { defineConfig, loadEnv } from "vite";
import checker from "vite-plugin-checker"; import checker from "vite-plugin-checker";
// import { libInjectCss } from 'vite-plugin-lib-inject-css'; import { libInjectCss } from 'vite-plugin-lib-inject-css';
export default ({ mode }) => { export default ({ mode }) => {
process.env = { ...process.env, ...loadEnv(mode, process.cwd()) }; process.env = { ...process.env, ...loadEnv(mode, process.cwd()) };
@@ -12,7 +12,7 @@ export default ({ mode }) => {
checker({ checker({
typescript: true, typescript: true,
}), }),
// libInjectCss(), libInjectCss(),
], ],
build: { build: {
cssCodeSplit: false, cssCodeSplit: false,

View File

@@ -2,6 +2,60 @@
# yarn lockfile v1 # yarn lockfile v1
"@ast-grep/napi-darwin-arm64@0.22.6":
version "0.22.6"
resolved "https://registry.yarnpkg.com/@ast-grep/napi-darwin-arm64/-/napi-darwin-arm64-0.22.6.tgz#34e9146234de6a7c965ed45335d67863ad96ca95"
integrity sha512-L9rEGJ8fNi5LxbZj860wbXxjX7DLNV799zcTaPOSzYadvNyhMY3LWvDXd45Vtx6Dh8QRtCoEMQmw8KaRCEjm9A==
"@ast-grep/napi-darwin-x64@0.22.6":
version "0.22.6"
resolved "https://registry.yarnpkg.com/@ast-grep/napi-darwin-x64/-/napi-darwin-x64-0.22.6.tgz#521470adf988e1f64e5912ec41afad3f958fc9ff"
integrity sha512-0iuM6iDJNhcPd6a/JJr64AallR7ttGW/MvUujfQdvJEZY5p9LK35xm23dULznW0tIMgwtMKPRaprgk8LPondKg==
"@ast-grep/napi-linux-arm64-gnu@0.22.6":
version "0.22.6"
resolved "https://registry.yarnpkg.com/@ast-grep/napi-linux-arm64-gnu/-/napi-linux-arm64-gnu-0.22.6.tgz#808008fd5952733e589558d5ac4a5746b84a1d55"
integrity sha512-9PAqNJlAQfFm1RW0DVCM/S4gFHdppxUTWacB3qEeJZXgdLnoH0KGQa4z3Xo559SPYDKZy0VnY02mZ3XJ+v6/Vw==
"@ast-grep/napi-linux-x64-gnu@0.22.6":
version "0.22.6"
resolved "https://registry.yarnpkg.com/@ast-grep/napi-linux-x64-gnu/-/napi-linux-x64-gnu-0.22.6.tgz#3f087687560b33ad9a5b232ff4e6780cc8367339"
integrity sha512-nZf+gxXVrZqvP1LN6HwzOMA4brF3umBXfMequQzv8S6HeJ4c34P23F0Tw8mHtQpVYP9PQWJUvt3LJQ8Xvd5Hiw==
"@ast-grep/napi-linux-x64-musl@0.22.6":
version "0.22.6"
resolved "https://registry.yarnpkg.com/@ast-grep/napi-linux-x64-musl/-/napi-linux-x64-musl-0.22.6.tgz#dfa09e6e947f266084b30080476e8a1e25aefc73"
integrity sha512-gcJeBMgJQf2pZZo0lgH0Vg4ycyujM7Am8VlomXhavC/dPpkddA1tiHSIC4fCNneLU1EqHITy3ALSmM4GLdsjBw==
"@ast-grep/napi-win32-arm64-msvc@0.22.6":
version "0.22.6"
resolved "https://registry.yarnpkg.com/@ast-grep/napi-win32-arm64-msvc/-/napi-win32-arm64-msvc-0.22.6.tgz#ac0f092c0dad39a05b8cb10430cdc99eb87eebfc"
integrity sha512-YDDzvPIyl4ti8xZfjvGSGVCX9JJjMQjyWPlXcwRpiLRnHThtHTDL8PyE2yq+gAPuZ28QbrygMkP9EKXIyYFVcQ==
"@ast-grep/napi-win32-ia32-msvc@0.22.6":
version "0.22.6"
resolved "https://registry.yarnpkg.com/@ast-grep/napi-win32-ia32-msvc/-/napi-win32-ia32-msvc-0.22.6.tgz#d4ca06d33a59760aa3870baffa296720ffb01b19"
integrity sha512-w5P0MDcBD3bifC2K9nCDEFYacy8HQnXdf6fX6cIE/7xL8XEDs6D1lQjGewrZDcMAXVXUQfupj4P27ZsJRmuIoQ==
"@ast-grep/napi-win32-x64-msvc@0.22.6":
version "0.22.6"
resolved "https://registry.yarnpkg.com/@ast-grep/napi-win32-x64-msvc/-/napi-win32-x64-msvc-0.22.6.tgz#82c3a7557336c0aa9809ac8ccd5ec573b907b727"
integrity sha512-1aaHvgsCBwUP0tDf4HXPMpUV/nUwsOWgRCiBc2zIJjdEjT9TTk795EIX9Z1Nc0OMCrxVEceyiKcYTofXa0Fpxw==
"@ast-grep/napi@^0.22.3":
version "0.22.6"
resolved "https://registry.yarnpkg.com/@ast-grep/napi/-/napi-0.22.6.tgz#473c4398fbafb39277c99b298f08d342f507eabe"
integrity sha512-kNF87HiI4omHC7VzyBZSvqOAXtMlSDRF2YX+O5ya0XKv/7/GYms1opLQ+BQ9twLLDj0WsSFX4MYg0TrinZTxTg==
optionalDependencies:
"@ast-grep/napi-darwin-arm64" "0.22.6"
"@ast-grep/napi-darwin-x64" "0.22.6"
"@ast-grep/napi-linux-arm64-gnu" "0.22.6"
"@ast-grep/napi-linux-x64-gnu" "0.22.6"
"@ast-grep/napi-linux-x64-musl" "0.22.6"
"@ast-grep/napi-win32-arm64-msvc" "0.22.6"
"@ast-grep/napi-win32-ia32-msvc" "0.22.6"
"@ast-grep/napi-win32-x64-msvc" "0.22.6"
"@babel/code-frame@^7.12.13": "@babel/code-frame@^7.12.13":
version "7.24.7" version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465"
@@ -135,6 +189,11 @@
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz" resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz"
integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==
"@jridgewell/sourcemap-codec@^1.4.15":
version "1.4.15"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
"@kintone/rest-api-client@^5.5.2": "@kintone/rest-api-client@^5.5.2":
version "5.5.2" version "5.5.2"
resolved "https://registry.yarnpkg.com/@kintone/rest-api-client/-/rest-api-client-5.5.2.tgz#501cd72dcfe51cd84c1a65fb1e2fdd4a92933e5b" resolved "https://registry.yarnpkg.com/@kintone/rest-api-client/-/rest-api-client-5.5.2.tgz#501cd72dcfe51cd84c1a65fb1e2fdd4a92933e5b"
@@ -660,6 +719,13 @@ jsonfile@^6.0.1:
optionalDependencies: optionalDependencies:
graceful-fs "^4.1.6" graceful-fs "^4.1.6"
magic-string@^0.30.10:
version "0.30.10"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e"
integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==
dependencies:
"@jridgewell/sourcemap-codec" "^1.4.15"
memorystream@^0.3.1: memorystream@^0.3.1:
version "0.3.1" version "0.3.1"
resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
@@ -961,6 +1027,20 @@ vite-plugin-checker@^0.6.4:
vscode-languageserver-textdocument "^1.0.1" vscode-languageserver-textdocument "^1.0.1"
vscode-uri "^3.0.2" vscode-uri "^3.0.2"
vite-plugin-css-injected-by-js@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.1.tgz#b9c568c21b131d08e31aa6d368ee39c9d6c1b6c1"
integrity sha512-9ioqwDuEBxW55gNoWFEDhfLTrVKXEEZgl5adhWmmqa88EQGKfTmexy4v1Rh0pAS6RhKQs2bUYQArprB32JpUZQ==
vite-plugin-lib-inject-css@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/vite-plugin-lib-inject-css/-/vite-plugin-lib-inject-css-2.1.1.tgz#39c5bb30dbb40c70e0d41a334097ce9b77e8e740"
integrity sha512-RIMeVnqBK/8I0E9nnQWzws6pdj5ilRMPJSnXYb6nWxNR4EmDPnksnb/ACoR5Fy7QfzULqS4gtQMrjwnNCC9zoA==
dependencies:
"@ast-grep/napi" "^0.22.3"
magic-string "^0.30.10"
picocolors "^1.0.0"
vite@^4.4.5: vite@^4.4.5:
version "4.5.0" version "4.5.0"
resolved "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz" resolved "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz"