Merge branch 'dev' into feature/validation-half-width

This commit is contained in:
kanarutsuda
2024-06-13 15:04:20 +09:00
36 changed files with 1550 additions and 567 deletions

View File

@@ -217,7 +217,9 @@ def deoployappfromkintone(app:str,revision:str,c:config.KINTONE_ENV):
data = {"apps":[{"app":app,"revision":revision}],"revert": False} data = {"apps":[{"app":app,"revision":revision}],"revert": False}
r = httpx.post(url,headers=headers,data=json.dumps(data)) r = httpx.post(url,headers=headers,data=json.dumps(data))
return r.json return r.json
# 既定項目に含めるアプリのフィールドのみ取得する
# スペース、枠線、ラベルを含まない
def getfieldsfromkintone(app:str,c:config.KINTONE_ENV): def getfieldsfromkintone(app:str,c:config.KINTONE_ENV):
headers={config.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE} headers={config.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE}
params = {"app":app} params = {"app":app}
@@ -225,6 +227,44 @@ def getfieldsfromkintone(app:str,c:config.KINTONE_ENV):
r = httpx.get(url,headers=headers,params=params) r = httpx.get(url,headers=headers,params=params)
return r.json() return r.json()
# フォームに配置するフィールドのみ取得する
# スペース、枠線、ラベルも含める
def getformfromkintone(app:str,c:config.KINTONE_ENV):
headers={config.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE}
params = {"app":app}
url = f"{c.BASE_URL}{config.API_V1_STR}/form.json"
r = httpx.get(url,headers=headers,params=params)
return r.json()
def merge_kintone_fields(fields_response: dict, form_response: dict) -> dict:
fields_properties = fields_response.get('properties', {})
form_properties = form_response.get('properties', [])
merged_properties = {k: v for k, v in fields_properties.items()}
for index, form_field in enumerate(form_properties):
code = form_field.get('code')
if code:
if code and code not in merged_properties:
merged_properties[code] = form_field
else:
element_id = form_field.get('elementId')
if element_id:
key = element_id
form_field['code']=element_id
form_field['label']=form_field.get('type')
# else:
# key = f"{form_field.get('type')}_{index}"
merged_properties[key] = form_field
merged_response = {
'revision': fields_response.get('revision', ''),
'properties': merged_properties
}
return merged_response
def analysefields(excel,kintone): def analysefields(excel,kintone):
updatefields={} updatefields={}
addfields={} addfields={}
@@ -482,6 +522,15 @@ async def appfields(request:Request,app:str,env = Depends(getkintoneenv)):
except Exception as e: except Exception as e:
raise APIException('kintone:appfields',request.url._url, f"Error occurred while get app fileds({env.DOMAIN_NAM}->{app}):",e) raise APIException('kintone:appfields',request.url._url, f"Error occurred while get app fileds({env.DOMAIN_NAM}->{app}):",e)
@r.get("/allfields")
async def allfields(request:Request,app:str,env = Depends(getkintoneenv)):
try:
field_resp = getfieldsfromkintone(app,env)
form_resp = getformfromkintone(app,env)
return merge_kintone_fields(field_resp,form_resp)
except Exception as e:
raise APIException('kintone:allfields',request.url._url, f"Error occurred while get form fileds({env.DOMAIN_NAM}->{app}):",e)
@r.get("/appprocess") @r.get("/appprocess")
async def appprocess(request:Request,app:str,env = Depends(getkintoneenv)): async def appprocess(request:Request,app:str,env = Depends(getkintoneenv)):
try: try:

View File

@@ -24,4 +24,8 @@ python -m venv env
```bash ```bash
pip install -r requirements.txt pip install -r requirements.txt
``` ```
4. backend 起動
```bash
uvicorn app.main:app --reload
```

View File

@@ -2,7 +2,6 @@
<html lang="ja-jp"> <html lang="ja-jp">
<head> <head>
<title><%= productName %></title> <title><%= productName %></title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="description" content="<%= productDescription %>"> <meta name="description" content="<%= productDescription %>">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@@ -17,8 +17,9 @@
}, },
"dependencies": { "dependencies": {
"@quasar/extras": "^1.16.4", "@quasar/extras": "^1.16.4",
"@vueuse/core": "^10.9.0",
"axios": "^1.4.0", "axios": "^1.4.0",
"pinia": "^2.1.6", "pinia": "^2.1.7",
"quasar": "^2.6.0", "quasar": "^2.6.0",
"uuid": "^9.0.0", "uuid": "^9.0.0",
"vue": "^3.0.0", "vue": "^3.0.0",

View File

@@ -4,6 +4,7 @@ import { Router } from 'vue-router';
import { App } from 'vue'; import { App } from 'vue';
export default boot(({ app, router }: { app: App<Element>; router: Router }) => { export default boot(({ app, router }: { app: App<Element>; router: Router }) => {
document.documentElement.lang="ja-JP";
app.config.errorHandler = (err: any, instance: any, info: string) => { app.config.errorHandler = (err: any, instance: any, info: string) => {
if (err.response && err.response.status === 401) { if (err.response && err.response.status === 401) {
// 認証エラーの場合再ログインする // 認証エラーの場合再ログインする

View File

@@ -1,5 +1,5 @@
<template> <template>
<show-dialog v-model:visible="showflg" name="条件エディタ" @close="closeDg" min-width="60vw" min-height="60vh"> <show-dialog v-model:visible="showflg" name="条件エディタ" @close="closeDg" min-width="50vw" min-height="60vh">
<template v-slot:toolbar> <template v-slot:toolbar>
<q-btn flat round dense icon="more_vert" > <q-btn flat round dense icon="more_vert" >
<q-menu auto-close anchor="bottom start"> <q-menu auto-close anchor="bottom start">

View File

@@ -6,21 +6,21 @@
{{ 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 }} {{ selectedObject.name.name }}
</q-chip> </q-chip>
</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"/>
</template> </template>
</q-field> </q-field>
<show-dialog v-model:visible="show" name="条件設定項目一覧" @close="closeDg" width="600px"> <show-dialog v-model:visible="show" name="設定項目一覧" @close="closeDg" min-width="400px">
<template v-slot:toolbar> <template v-slot:toolbar>
<q-input dense debounce="200" v-model="filter" placeholder="検索" clearable> <q-input dense debounce="200" v-model="filter" placeholder="検索" clearable>
<template v-slot:before> <template v-slot:before>
<q-icon name="search" /> <q-icon name="search" />
</template> </template>
</q-input> </q-input>
</template> </template>
<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>
</show-dialog> </show-dialog>
</template> </template>
@@ -88,9 +88,9 @@
.condition-object{ .condition-object{
min-width: 200px; min-width: 200px;
max-height: 40px; max-height: 40px;
padding: 2px; margin: 0 2px;
} }
.selected-obj{ .selected-obj{
margin: 0px; margin: 0 2px;
} }
</style> </style>

View File

@@ -66,7 +66,7 @@
</div> </div>
<!-- condition --> <!-- condition -->
<div @click.stop @keypress.stop v-else > <div @click.stop @keypress.stop v-else >
<div class="row no-wrap items-center"> <div class="row no-wrap items-center q-my-xs">
<ConditionObject v-bind="prop.node" v-model="prop.node.object" class="col-4"></ConditionObject> <ConditionObject v-bind="prop.node" v-model="prop.node.object" class="col-4"></ConditionObject>
<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>
<q-input v-if="!prop.node.object || !('options' in prop.node.object)" <q-input v-if="!prop.node.object || !('options' in prop.node.object)"
@@ -257,12 +257,12 @@ export default defineComponent( {
.condition-value{ .condition-value{
min-width: 200px; min-width: 200px;
max-height: 40px; max-height: 40px;
padding: 2px; margin: 0 2px;
} }
.operator{ .operator{
min-width: 150px; min-width: 150px;
max-height: 40px; max-height: 40px;
padding: 2px; margin: 0 2px;
text-align: center; text-align: center;
font-size: 12pt; font-size: 12pt;
} }

View File

@@ -19,7 +19,7 @@
<q-tab-panels v-model="tab" animated> <q-tab-panels v-model="tab" animated>
<q-tab-panel name="fields"> <q-tab-panel name="fields">
<field-list v-model="selected" type="single" :filter="filter" :appId="appId"></field-list> <field-list v-model="selected" type="single" :filter="filter" :appId="sourceApp ? sourceApp :appId " :fields="sourceFields"></field-list>
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="vars" > <q-tab-panel name="vars" >
@@ -30,7 +30,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { ref, onMounted, reactive } from 'vue' import { ref, onMounted, reactive, inject } from 'vue'
import FieldList from './FieldList.vue'; import FieldList from './FieldList.vue';
import VariableList from './VariableList.vue'; import VariableList from './VariableList.vue';
@@ -48,10 +48,14 @@ export default {
filter:String filter:String
}, },
setup(props) { setup(props) {
const selected = ref([]);
console.log(selected);
return { return {
sourceFields : inject('sourceFields'),
sourceApp : inject('sourceApp'),
tab: ref('fields'), tab: ref('fields'),
selected: ref([]) selected
} }
}, },

View File

@@ -1,51 +1,51 @@
<template> <template>
<div class="q-pa-md"> <div class="q-pa-md">
<q-table flat bordered :loading="!isLoaded" row-key="name" :selection="type" <q-table flat bordered :loading="!isLoaded" row-key="name" :selection="type" :selected="modelValue"
:selected="modelValue" @update:selected="$emit('update:modelValue', $event)" :filter="filter" :columns="columns" :rows="rows" />
@update:selected="$emit('update:modelValue', $event)"
:filter="filter"
:columns="columns" :rows="rows" />
</div> </div>
</template> </template>
<script> <script lang="ts">
import { ref, onMounted, reactive } from 'vue' import { useAsyncState } from '@vueuse/core';
import { api } from 'boot/axios'; import { api } from 'boot/axios';
import { computed } from 'vue';
export default { export default {
name: 'FieldList', name: 'FieldList',
props: { props: {
fields: Array,
name: String, name: String,
type: String, type: String,
appId: Number, appId: Number,
modelValue:Array, modelValue: Array,
filter:String filter: String
}, },
emits:[ emits: [
'update:modelValue' 'update:modelValue'
], ],
setup(props) { setup(props) {
const isLoaded = ref(false); // const rows = ref([]);
// const isLoaded = ref(false);
const columns = [ const columns = [
{ name: 'name', required: true, label: 'フィールド名', align: 'left', field: row => row.name, sortable: true }, { name: 'name', required: true, label: 'フィールド名', align: 'left', field: 'name', sortable: true },
{ name: 'code', label: 'フィールドコード', align: 'left', field: 'code', sortable: true }, { name: 'code', label: 'フィールドコード', align: 'left', field: 'code', sortable: true },
{ name: 'type', label: 'フィールドタイプ', align: 'left', field: 'type', sortable: true } { name: 'type', label: 'フィールドタイプ', align: 'left', field: 'type', sortable: true }
] ]
const rows = reactive([]);
onMounted(async () => {
const res = await api.get('api/v1/appfields', {
params: {
app: props.appId
}
});
let fields = res.data.properties;
console.log(fields);
Object.keys(fields).forEach((key) => {
const fld = fields[key];
rows.push({ name: fld.label, objectType: 'field', ...fld });
});
isLoaded.value = true;
});
const { state : rows, isReady: isLoaded, isLoading } = useAsyncState((args) => {
if (props.fields) {
return props.fields.map(f => ({ name: f.label, objectType: 'field', ...f }));
} else {
return api.get('api/v1/appfields', {
params: {
app: props.appId
}
}).then(res => {
console.log(res);
return Object.values(res.data.properties).map(f => ({ name: f.label, objectType: 'field', ...f }));
});
}
}, [{ name: '', objectType: '', type: '', code: '', label: '' }])
return { return {
columns, columns,
rows, rows,

View File

@@ -11,6 +11,7 @@
import { ref, onMounted, reactive, watchEffect } from 'vue' import { ref, onMounted, reactive, watchEffect } from 'vue'
import { api } from 'boot/axios'; import { api } from 'boot/axios';
export default { export default {
name: 'fieldSelect', name: 'fieldSelect',
props: { props: {
@@ -28,8 +29,9 @@ export default {
type:Array, type:Array,
default:()=>[] default:()=>[]
}, },
updateSelects: { fieldTypes:{
type: Function type:Array,
default:()=>[]
}, },
filter: String, filter: String,
}, },
@@ -43,29 +45,26 @@ export default {
const pageSetting = ref({ const pageSetting = ref({
sortBy: 'desc', sortBy: 'desc',
descending: false, descending: false,
page: 2, page: 1,
rowsPerPage: props.not_page ? 0 : 5 rowsPerPage: props.not_page ? 0 : 5
// rowsNumber: xx if getting data from a server // rowsNumber: xx if getting data from a server
}); });
const rows = reactive([]); const rows = reactive([]);
const selected = ref(props.selectedFields && props.selectedFields.length>0?props.selectedFields:[]); const selected = ref(props.selectedFields && props.selectedFields.length>0?props.selectedFields:[]);
watchEffect(() => {
props.updateSelects(selected);
});
onMounted(async () => { onMounted(async () => {
const res = await api.get('api/v1/appfields', { const url = props.fieldTypes.includes('SPACER')?'api/v1/allfields':'api/v1/appfields';
const res = await api.get(url, {
params: { params: {
app: props.appId app: props.appId
} }
}); });
let fields = res.data.properties; let fields = res.data.properties;
console.log(fields);
Object.keys(fields).forEach((key) => { Object.keys(fields).forEach((key) => {
const fld = fields[key]; const fld = fields[key];
// rows.push({name:fields[key].label,code:fields[key].code,type:fields[key].type}); if(props.fieldTypes.length===0 || props.fieldTypes.includes(fld.type)){
rows.push({ name: fld.label, ...fld }); rows.push({ name: fld.label || fld.code, ...fld });
}
}); });
isLoaded.value = true; isLoaded.value = true;
}); });

View File

@@ -1,7 +1,7 @@
<template> <template>
<!-- <div class="q-pa-md q-gutter-sm" > --> <!-- <div class="q-pa-md q-gutter-sm" > -->
<q-dialog :model-value="visible" persistent bordered > <q-dialog :model-value="visible" persistent bordered >
<q-card :style="cardStyle" style=" min-width: 40vw; max-width: 80vw; max-height: 95vh;"> <q-card style="min-width: 40vw; max-width: 80vw; max-height: 95vh;" :style="cardStyle">
<q-toolbar class="bg-grey-4"> <q-toolbar class="bg-grey-4">
<q-toolbar-title>{{ name }}</q-toolbar-title> <q-toolbar-title>{{ name }}</q-toolbar-title>
<q-space></q-space> <q-space></q-space>

View File

@@ -1,43 +1,59 @@
<template> <template>
<div class="q-pa-md"> <div class="q-pa-md">
<q-table flat bordered row-key="name" :selection="type" <q-table flat bordered row-key="id" :selection="type" :selected="modelValue"
:selected="modelValue" @update:selected="$emit('update:modelValue', $event)" :columns="columns" :rows="rows" />
@update:selected="$emit('update:modelValue', $event)"
:columns="columns" :rows="rows" />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { ref, reactive, PropType, compile } from 'vue'; import { PropType, reactive } from 'vue';
import {IActionNode,IActionVariable} from '../types/ActionTypes'; import { IActionVariable } from '../types/ActionTypes';
import { v4 as uuidv4 } from 'uuid';
export default { export default {
name: 'VariableList', name: 'VariableList',
props: { props: {
name: String, name: String,
type: String, type: String,
vars:{ vars: {
type:Array as PropType<IActionVariable[]>, type: Array as PropType<IActionVariable[]>,
reqired:true, reqired: true,
default:()=>[] default: () => []
}, },
modelValue:Array modelValue: Array
}, },
emits:[ emits: [
'update:modelValue' 'update:modelValue'
], ],
setup(props) { setup(props) {
const columns= [ const variableName = (field) => {
{ name: 'actionName', label: 'アクション名',align: 'left',field: 'actionName',sortable: true}, const name = field.name;
{ name: 'displayName', label: '変数表示名', align: 'left',field: 'displayName', sortable: true }, return name.name;
{ name: 'name', label: '変数名', align: 'left',field: 'name',required: true, sortable: true } }
const columns = [
{ name: 'actionName', label: 'アクション名', align: 'left', field: 'actionName', sortable: true },
{ name: 'displayName', label: '変数表示名', align: 'left', field: 'displayName', sortable: true },
{ name: 'name', label: '変数名', align: 'left', field: variableName, required: true, sortable: true }
]; ];
const rows= props.vars.map((v)=>{
return {objectType:'variable',...v}; const rows = props.vars.flatMap((v) => {
if (v.name.vars && v.name.vars.length > 0) {
return v.name.vars
.filter(o => o.vName && o.logicalOperator && o.field)
.map(o => ({
id: uuidv4(),
objectType: 'variable',
name: { name: `${v.name.name}.${o.vName}` },
actionName: v.name.actionName,
displayName: v.name.displayName
}));
} else {
return [{ objectType: 'variable', ...v }];
}
}); });
return { return {
columns, columns,
rows:reactive(rows) rows: reactive(rows)
} }
} }
} }

View File

@@ -1,48 +1,51 @@
<template> <template>
<!-- <div class="q-pa-md q-gutter-sm"> --> <!-- <div class="q-pa-md q-gutter-sm"> -->
<q-tree <q-tree :nodes="store.eventTree.screens" node-key="eventId" children-key="events" no-connectors
:nodes="store.eventTree.screens" v-model:expanded="store.expandedScreen" :dense="true" :ref="tree">
node-key="eventId" <template v-slot:header-EVENT="prop">
children-key="events" <div :ref="prop.node.eventId" class="row col items-center no-wrap event-node" @click="onSelected(prop.node)">
no-connectors <q-icon v-if="prop.node.eventId" name="play_circle" :color="prop.node.hasFlow ? 'green' : 'grey'" size="16px"
v-model:expanded="store.expandedScreen" class="q-mr-sm">
:dense="true" </q-icon>
:ref="tree" <div class="no-wrap"
> :class="selectedEvent && prop.node.eventId === selectedEvent.eventId ? 'selected-node' : ''">{{
<template v-slot:header-EVENT="prop"> prop.node.label }}</div>
<div class="row col items-start no-wrap event-node" @click="onSelected(prop.node)"> <q-space></q-space>
<q-icon v-if="prop.node.eventId" <!-- <q-icon v-if="prop.node.hasFlow" name="delete" color="negative" size="16px" class="q-mr-sm"></q-icon> -->
name="play_circle" </div>
:color="prop.node.hasFlow?'green':'grey'" </template>
size="16px" class="q-mr-sm"> <template v-slot:header-CHANGE="prop">
</q-icon> <div class="row col items-start no-wrap event-node">
<div class="no-wrap" :class="selectedEvent && prop.node.eventId===selectedEvent.eventId?'selected-node':''">{{ prop.node.label }}</div> <div class="no-wrap"
:class="selectedEvent && prop.node.eventId === selectedEvent.eventId ? 'selected-node' : ''"
>{{ prop.node.label }}</div>
<q-space></q-space>
<q-icon name="add_circle" color="primary" size="16px" class="q-mr-sm"
@click="addChangeEvent(prop.node)"></q-icon>
</div>
</template>
<template v-slot:header-DELETABLE="prop">
<div class="row col items-start event-node" @click="onSelected(prop.node)">
<q-icon v-if="prop.node.eventId" name="play_circle" :color="prop.node.hasFlow ? 'green' : 'grey'" size="16px" class="q-mr-sm" />
<div class="no-wrap" :class="selectedEvent && prop.node.eventId === selectedEvent.eventId ? 'selected-node' : ''" >{{ prop.node.label }}</div>
<q-space></q-space> <q-space></q-space>
<!-- <q-icon v-if="prop.node.hasFlow" name="delete" color="negative" size="16px" class="q-mr-sm"></q-icon> --> <q-icon name="delete_forever" color="negative" size="16px" @click="deleteEvent(prop.node)"></q-icon>
</div> </div>
</template> </template>
<template v-slot:header-CHANGE="prop" > </q-tree>
<div class="row col items-start no-wrap event-node" > <show-dialog v-model:visible="showDialog" name="フィールド選択" @close="closeDg">
<div class="no-wrap">{{ prop.node.label }}</div> <field-select ref="appDg" name="フィールド" type="single" :appId="store.appInfo?.appId"></field-select>
<q-space></q-space> </show-dialog>
<q-icon name="add_circle" color="primary" size="16px" class="q-mr-sm" @click="addChangeEvent(prop.node)"></q-icon>
</div>
</template>
</q-tree>
<show-dialog v-model:visible="showDialog" name="フィールド選択" @close="closeDg" widht="400px">
<field-select ref="appDg" name="フィールド" type="single" :appId="store.appInfo?.appId"></field-select>
</show-dialog>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, computed, ref } from 'vue'; import { QTree, useQuasar } from 'quasar';
import { IKintoneEvent ,IKintoneEventGroup, IKintoneEventNode, kintoneEvent} from '../../types/KintoneEvents'; import { ActionFlow, RootAction } from 'src/types/ActionTypes';
import { storeToRefs } from 'pinia';
import { useFlowEditorStore } from 'stores/flowEditor'; import { useFlowEditorStore } from 'stores/flowEditor';
import { ActionFlow, ActionNode, RootAction } from 'src/types/ActionTypes'; import { defineComponent, ref } from 'vue';
import ShowDialog from '../ShowDialog.vue'; import { IKintoneEvent, IKintoneEventGroup, IKintoneEventNode } from '../../types/KintoneEvents';
import FieldSelect from '../FieldSelect.vue'; import FieldSelect from '../FieldSelect.vue';
import { QTree } from 'quasar'; import ShowDialog from '../ShowDialog.vue';
export default defineComponent({ export default defineComponent({
name: 'EventTree', name: 'EventTree',
components: { components: {
@@ -50,6 +53,7 @@ export default defineComponent({
FieldSelect, FieldSelect,
}, },
setup(props, context) { setup(props, context) {
const $q = useQuasar();
const appDg = ref(); const appDg = ref();
const store = useFlowEditorStore(); const store = useFlowEditorStore();
const showDialog = ref(false); const showDialog = ref(false);
@@ -58,62 +62,79 @@ export default defineComponent({
// const selectedFlow = store.currentFlow; // const selectedFlow = store.currentFlow;
// const expanded=ref(); // const expanded=ref();
const selectedEvent = ref<IKintoneEvent|null>(null); const selectedEvent = ref<IKintoneEvent | null>(null);
const selectedChangeEvent=ref<IKintoneEventGroup|null>(null); const selectedChangeEvent = ref<IKintoneEventGroup | null>(null);
const isFieldChange = (node:IKintoneEventNode)=>{ const isFieldChange = (node: IKintoneEventNode) => {
return node.header=='EVENT' && node.eventId.indexOf(".change.")>-1; return node.header == 'EVENT' && node.eventId.indexOf(".change.") > -1;
} }
//フィールド値変更イベント追加 //フィールド値変更イベント追加
const closeDg = (val:string) => { const closeDg = (val: string) => {
if (val == 'OK') { if (val == 'OK') {
if(!selectedChangeEvent.value){return;} if (!selectedChangeEvent.value) { return; }
const field = appDg.value.selected[0]; const field = appDg.value.selected[0];
const eventid = `${selectedChangeEvent.value.eventId}.${field.code}`; const eventid = `${selectedChangeEvent.value.eventId}.${field.code}`;
if(store.eventTree.findEventById(eventid)){ if (store.eventTree.findEventById(eventid)) {
return; return;
} }
selectedChangeEvent.value?.events.push( selectedChangeEvent.value?.events.push({
new kintoneEvent( eventId: eventid,
field.label, label: field.name,
eventid, parentId: selectedChangeEvent.value.eventId,
selectedChangeEvent.value.eventId) header: 'DELETABLE'
); });
tree.value?.expanded?.push(selectedChangeEvent.value.eventId); tree.value?.expanded?.push(selectedChangeEvent.value.eventId);
tree.value?.expandAll(); tree.value?.expandAll();
} }
}; };
const addChangeEvent=(node:IKintoneEventGroup)=>{ const addChangeEvent = (node: IKintoneEventGroup) => {
if(store.appInfo===undefined){ if (store.appInfo === undefined) {
return; return;
} }
selectedChangeEvent.value=node; selectedChangeEvent.value = node;
showDialog.value=true; showDialog.value = true;
} }
const onSelected=(node:IKintoneEvent)=>{
if(!node.eventId){ const deleteEvent = (node: IKintoneEvent) => {
return; if (!node.eventId) {
} return;
selectedEvent.value=node; }
if(store.appInfo===undefined){ store.deleteEvent(node);
return; store.selectFlow(undefined)
}
const screen = store.eventTree.findEventById(node.parentId); $q.notify({
let flow =store.findFlowByEventId(node.eventId); type: 'positive',
let screenName=screen!==null?screen.label:""; caption: "通知",
let nodeLabel = node.label; message: `イベント ${node.label} 削除`
// if(isFieldChange(node)){ })
// screenName=nodeLabel; }
// nodeLabel=`${node.label}の値を変更したとき`;
// } const onSelected = (node: IKintoneEvent) => {
if(flow!==undefined && flow!==null ){ if (!node.eventId) {
store.selectFlow(flow); return;
}else{ }
const root = new RootAction(node.eventId,screenName,nodeLabel) selectedEvent.value = node;
const flow =new ActionFlow(root); if (store.appInfo === undefined) {
store.flows?.push(flow); return;
store.selectFlow(flow); }
selectedEvent.value.flowData=flow; const screen = store.eventTree.findEventById(node.parentId);
}
let flow = store.findFlowByEventId(node.eventId);
let screenName = screen !== null ? screen.label : "";
let nodeLabel = node.label;
// if(isFieldChange(node)){
// screenName=nodeLabel;
// nodeLabel=`${node.label}の値を変更したとき`;
// }
if (flow !== undefined && flow !== null) {
store.selectFlow(flow);
} else {
const root = new RootAction(node.eventId, screenName, nodeLabel)
const flow = new ActionFlow(root);
store.flows?.push(flow);
store.selectFlow(flow);
selectedEvent.value.flowData = flow;
}
}; };
return { return {
// eventTree, // eventTree,
@@ -125,6 +146,7 @@ export default defineComponent({
onSelected, onSelected,
selectedEvent, selectedEvent,
addChangeEvent, addChangeEvent,
deleteEvent,
closeDg, closeDg,
store store
} }
@@ -132,20 +154,25 @@ export default defineComponent({
}); });
</script> </script>
<style lang="scss"> <style lang="scss">
.nowrap{ .nowrap {
flex-wrap:nowarp; flex-wrap: nowarp;
text-wrap:nowarp; text-wrap: nowarp;
} }
.event-node{
cursor:pointer; .event-node {
cursor: pointer;
} }
.selected-node{
.selected-node {
color: $primary; color: $primary;
font-weight: bolder; font-weight: bolder;
} }
.event-node:hover{
.event-node:hover {
background-color: $light-blue-1; background-color: $light-blue-1;
} }
.delete-btn {
margin-right: 5px;
}
</style> </style>

View File

@@ -205,7 +205,7 @@ export default defineComponent({
*/ */
const varName =(node:IActionNode)=>{ const varName =(node:IActionNode)=>{
const prop = node.actionProps.find((prop) => prop.props.name === "verName"); const prop = node.actionProps.find((prop) => prop.props.name === "verName");
return prop?.props.modelValue; return prop?.props.modelValue.name;
}; };
const copyFlow=()=>{ const copyFlow=()=>{
context.emit('copyFlow', props.actionNode); context.emit('copyFlow', props.actionNode);

View File

@@ -23,9 +23,9 @@
<q-virtual-scroll style="max-height: 160px;" :items="selectedField.fields" separator v-slot="{ item, index }"> <q-virtual-scroll style="max-height: 160px;" :items="selectedField.fields" separator v-slot="{ item, index }">
<q-item :key="index" dense clickable > <q-item :key="index" dense clickable >
<q-item-section> <q-item-section>
<q-item-label> <q-item-label>
{{ item.label }} {{ item.label }}
</q-item-label> </q-item-label>
</q-item-section> </q-item-section>
<q-item-section side> <q-item-section side>
<q-btn round flat size="sm" icon="clear" @click="removeField(index)" /> <q-btn round flat size="sm" icon="clear" @click="removeField(index)" />
@@ -81,8 +81,8 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<field-select ref="fieldDlg" name="フィールド" :type="selectType" :updateSelects="updateItems" <field-select ref="fieldDlg" name="フィールド" :type="selectType"
:appId="selectedField.app?.id" not_page :filter="fieldFilter" :selectedFields="selectedField.fields"></field-select> :appId="selectedField.app?.id" not_page :filter="fieldFilter" :selectedFields="selectedField.fields" :fieldTypes="fieldTypes"></field-select>
</div> </div>
</div> </div>
</div> </div>
@@ -99,9 +99,7 @@
</template> </template>
</q-input> </q-input>
</template> </template>
<AppSelect ref="appDlg" name="アプリ" type="single" :filter="filter" ></AppSelect>
<AppSelect ref="appDlg" name="アプリ" type="single" :filter="filter"
:updateExternalSelectAppInfo="updateExternalSelectAppInfo"></AppSelect>
</show-dialog> </show-dialog>
</template> </template>
@@ -128,7 +126,7 @@ interface IAppFields{
export default defineComponent({ export default defineComponent({
inheritAttrs:false, inheritAttrs:false,
name: 'FieldInput', name: 'AppFieldSelect',
components: { components: {
ShowDialog, ShowDialog,
FieldSelect, FieldSelect,
@@ -154,6 +152,10 @@ export default defineComponent({
selectType:{ selectType:{
type:String, type:String,
default:'single' default:'single'
},
fieldTypes:{
type:Array,
default:()=>[]
} }
}, },
setup(props, { emit }) { setup(props, { emit }) {
@@ -197,13 +199,6 @@ export default defineComponent({
selectedField.value.fields = fieldDlg.value.selected; selectedField.value.fields = fieldDlg.value.selected;
} }
}; };
const updateExternalSelectAppInfo = (newAppinfo:IApp) => {
// selectedField.value.app = newAppinfo
}
const updateItems = (newFields:IField[]) => {
// selectedField.value.fields = newFields
}
const removeField=(index:number)=>{ const removeField=(index:number)=>{
selectedField.value.fields.splice(index,1); selectedField.value.fields.splice(index,1);
@@ -223,9 +218,7 @@ export default defineComponent({
selectedField, selectedField,
showSelectApp, showSelectApp,
isSelected, isSelected,
updateExternalSelectAppInfo,
filter: ref(), filter: ref(),
updateItems,
clear, clear,
fieldFilter: ref(), fieldFilter: ref(),
removeField removeField

View File

@@ -1,12 +1,12 @@
<template> <template>
<div v-bind="$attrs"> <div v-bind="$attrs">
<q-field v-model="tree" :label="displayName" labelColor="primary" stack-label > <q-field v-model="tree" :label="displayName" labelColor="primary" stack-label>
<template v-slot:control > <template v-slot:control>
<q-card flat class="full-width"> <q-card flat class="full-width">
<q-card-actions vertical> <q-card-actions vertical>
<q-btn color="grey-3" text-color="black" @click="showDg()">クリックで設定{{ isSetted?'設定済み':'未設定' }}</q-btn> <q-btn color="grey-3" text-color="black" @click="showDg()">クリックで設定{{ isSetted ? '設定済み' : '未設定' }}</q-btn>
</q-card-actions> </q-card-actions>
<q-card-section class="text-caption" > <q-card-section class="text-caption">
<div v-if="!isSetted">{{ placeholder }}</div> <div v-if="!isSetted">{{ placeholder }}</div>
<div v-else>{{ conditionString }}</div> <div v-else>{{ conditionString }}</div>
</q-card-section> </q-card-section>
@@ -17,82 +17,118 @@
</div> </div>
</template> </template>
<script lang="ts">
import { defineComponent, ref ,watchEffect,computed,reactive} from 'vue';
import { ConditionTree,GroupNode,ConditionNode,LogicalOperator,Operator } from 'app/src/types/Conditions';
import ConditionEditor from '../ConditionEditor/ConditionEditor.vue'
export default defineComponent({
name: 'FieldInput',
inheritAttrs:false,
components: {
ConditionEditor
},
props: {
displayName:{
type: String,
default: '',
},
name:{
type: String,
default: '',
},
placeholder: {
type: String,
default: '',
},
hint:{
type: String,
default: '',
},
modelValue: {
type: String,
default: null
},
},
setup(props, { emit }) {
const appDg = ref();
const show = ref(false);
const tree = reactive(new ConditionTree());
if(props.modelValue && props.modelValue!==''){
tree.fromJson(props.modelValue);
}else{
const newNode = new ConditionNode({},Operator.Equal,'',tree.root);
tree.addNode(tree.root,newNode);
}
const isSetted=ref(props.modelValue && props.modelValue!==''); <script lang="ts">
import { ConditionNode, ConditionTree, Operator } from 'app/src/types/Conditions';
import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue';
import ConditionEditor from '../ConditionEditor/ConditionEditor.vue';
const conditionString = computed(()=>{ type Props = {
return tree.buildConditionString(tree.root); props?: {
}); name: string;
modelValue?: {
const showDg = () => { fields: {
show.value = true; type: string;
}; label: string;
code: string;
const onClosed = (val:string) => { }[]
if (val == 'OK') {
const conditionJson = tree.toJson();
isSetted.value=true;
emit('update:modelValue', conditionJson);
}
};
watchEffect(() => {
const conditionJson = tree.toJson();
emit('update:modelValue', conditionJson);
});
return {
appDg,
isSetted,
show,
showDg,
onClosed,
tree,
conditionString
};
} }
}); }
</script> };
export default defineComponent({
name: 'FieldInput',
inheritAttrs: false,
components: {
ConditionEditor
},
props: {
context: {
type: Array<Props>,
default: '',
},
displayName: {
type: String,
default: '',
},
name: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '',
},
hint: {
type: String,
default: '',
},
modelValue: {
type: String,
default: null
},
sourceType: {
type: String,
default: 'field'
}
},
setup(props, { emit }) {
const source = props.context.find(element => element?.props?.name === 'sources')
if (source) {
if(props.sourceType === 'field'){
provide('sourceFields', computed( () => source.props?.modelValue?.fields ?? []));
} else if(props.sourceType === 'app'){
console.log('sourceApp', source.props?.modelValue);
provide('sourceApp', computed( () => source.props?.modelValue?.app?.id));
}
}
const appDg = ref();
const show = ref(false);
const tree = reactive(new ConditionTree());
if (props.modelValue && props.modelValue !== '') {
tree.fromJson(props.modelValue);
} else {
const newNode = new ConditionNode({}, Operator.Equal, '', tree.root);
tree.addNode(tree.root, newNode);
}
const isSetted = ref(props.modelValue && props.modelValue !== '');
const conditionString = computed(() => {
return tree.buildConditionString(tree.root);
});
const showDg = () => {
show.value = true;
};
const onClosed = (val: string) => {
if (val == 'OK') {
const conditionJson = tree.toJson();
isSetted.value = true;
emit('update:modelValue', conditionJson);
}
};
watchEffect(() => {
const conditionJson = tree.toJson();
emit('update:modelValue', conditionJson);
});
return {
appDg,
isSetted,
show,
showDg,
onClosed,
tree,
conditionString
};
}
});
</script>

View File

@@ -0,0 +1,229 @@
<template>
<div>
<q-field :label="displayName" labelColor="primary" stack-label>
<template v-slot:control>
<q-card flat class="full-width">
<q-card-actions vertical>
<q-btn color="grey-3" text-color="black" @click="() => { dgIsShow = true }">クリックで設定</q-btn>
</q-card-actions>
<q-card-section class="text-caption">
<div v-if="processingObjectsInputDisplay && processingObjectsInputDisplay.length>0">
<div v-for="(item) in processingObjectsInputDisplay" :key="item">{{ item }}</div>
</div>
<div v-else>{{ placeholder }}</div>
</q-card-section>
</q-card>
</template>
</q-field>
<show-dialog v-model:visible="dgIsShow" name="集計処理" @close="closeDg" min-width="50vw" min-height="60vh">
<div class="q-mx-md q-mb-md">
<q-input v-model="processingProps.name" type="text" label-color="primary" label="集計結果の変数名"
placeholder="集計結果を格納する変数名を入力してください" stack-label />
</div>
<div class="q-mx-md">
<div class="row q-col-gutter-x-xs flex-center">
<div class="col-5">
<div class="q-mx-xs">データソース</div>
</div>
<div class="col-2">
<div class="q-mx-xs">集計計算</div>
</div>
<div class="col-4">
<div class="q-mx-xs">集計結果変数名</div>
</div>
<div class="col-1"><q-btn flat round dense icon="add" size="sm" @click="addProcessingObject" />
</div>
</div>
<div class="q-my-sm" v-for="(item, index) in processingObjects" :key="item.id">
<div class="row q-col-gutter-x-xs flex-center">
<div class="col-5">
<ConditionObject v-model="item.field" />
</div>
<div class="col-2">
<q-select v-model="item.logicalOperator" :options="logicalOperators" outlined dense></q-select>
</div>
<div class="col-4">
<q-input v-model="item.vName" type="text" outlined dense />
</div>
<div class="col-1">
<q-btn flat round dense icon="delete" size="sm" @click="() => deleteProcessingObject(index)" />
</div>
</div>
</div>
</div>
</show-dialog>
</div>
</template>
<script lang="ts">
import { v4 as uuidv4 } from 'uuid';
import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue';
import ConditionObject from '../ConditionEditor/ConditionObject.vue';
import ShowDialog from '../ShowDialog.vue';
type Props = {
props?: {
name: string;
modelValue?: {
fields: {
type: string;
label: string;
code: string;
}[]
} | string
}
};
type ProcessingObjectType = {
field?: {
name: string | {
name: string;
};
objectType: string;
type: string;
code: string;
label: string;
noLabel: boolean;
};
logicalOperator?: string;
vName?: string;
id: string;
}
type ValueType = {
name: string;
actionName: string,
displayName: string,
vars: ProcessingObjectType[];
}
export default defineComponent({
name: 'DataProcessing',
inheritAttrs: false,
components: {
ShowDialog,
ConditionObject,
},
props: {
context: {
type: Array<Props>,
default: '',
},
displayName: {
type: String,
default: '',
},
name: {
type: String,
default: '',
},
modelValue: {
type: Object as () => ValueType,
},
placeholder: {
type: String,
default: '',
},
},
setup(props, { emit }) {
const source = props.context.find(element => element?.props?.name === 'sources')
if (source) {
provide('sourceFields', computed(() => {
const modelValue = source.props?.modelValue;
if (modelValue && typeof modelValue !== 'string') {
return modelValue.fields;
}
return null;
}));
}
const actionName = props.context.find(element => element?.props?.name === 'displayName')
const processingProps: ValueType = props.modelValue && props.modelValue.vars
? props.modelValue
: reactive({
name: '',
actionName: actionName?.props?.modelValue as string,
displayName: '結果(戻り値)',
vars: [{ id: uuidv4() }]
});
const closeDg = () => {
emit('update:modelValue', processingProps
);
}
const processingObjects = processingProps.vars;
const deleteProcessingObject = (index: number) => processingObjects.length === 1
? processingObjects.splice(0, processingObjects.length, { id: uuidv4() })
: processingObjects.splice(index, 1);
const processingObjectsInputDisplay = computed(() =>
processingObjects ?
processingObjects
.filter(item => item.field && item.logicalOperator && item.vName)
.map(item => {
const name = typeof item.field?.name === 'string'
? item.field.name
: item.field?.name.name;
return item.logicalOperator.operator!==''?
`${processingProps.name}.${item.vName} = ${item.logicalOperator.operator}(${name})`
:`${processingProps.name}.${item.vName} = ${name}`
})
: []
);
//集計処理方法
const logicalOperators = ref([
{
"operator": "",
"label": "なし"
},
{
"operator": "SUM",
"label": "合計"
},
{
"operator": "AVG",
"label": "平均"
},
{
"operator": "MAX",
"label": "最大値"
},
{
"operator": "MIN",
"label": "最小値"
},
{
"operator": "COUNT",
"label": "カウント"
},
{
"operator": "FIRST",
"label": "最初の値"
}
]);
watchEffect(() => {
emit('update:modelValue', processingProps);
});
return {
uuidv4,
dgIsShow: ref(false),
closeDg,
processingObjects,
processingProps,
addProcessingObject: () => processingObjects.push({ id: uuidv4() }),
deleteProcessingObject,
logicalOperators,
processingObjectsInputDisplay,
};
},
});
</script>
<style lang="scss"></style>

View File

@@ -61,12 +61,12 @@ export default defineComponent({
if(store.eventTree.findEventById(addEventId)){ if(store.eventTree.findEventById(addEventId)){
return; return;
} }
customEvents.events.push( customEvents.events.push({
new kintoneEvent( eventId: addEventId,
displayName, label: displayName,
addEventId, parentId: customButtonId,
customButtonId) header: 'DELETABLE'
); });
} }
} }

View File

@@ -7,9 +7,6 @@
{{ selectedField.name }} {{ selectedField.name }}
</q-chip> </q-chip>
</template> </template>
<!-- <template v-slot:hint v-if="isSelected">
<div> 項目コード<q-chip size="sm" outline color="secondary" text-color="white">{{selectedField.code}}</q-chip></div>
</template> -->
<template v-slot:hint v-if="!isSelected"> <template v-slot:hint v-if="!isSelected">
{{ placeholder }} {{ placeholder }}
</template> </template>
@@ -19,7 +16,7 @@
</template> </template>
</q-field> </q-field>
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeDg" widht="400px"> <show-dialog v-model:visible="show" name="フィールド一覧" @close="closeDg" widht="400px">
<field-select ref="appDg" name="フィールド" type="single" :appId="store.appInfo?.appId"></field-select> <field-select ref="appDg" name="フィールド" :type="selectType" :appId="store.appInfo?.appId" :fieldTypes="fieldTypes"></field-select>
</show-dialog> </show-dialog>
</div> </div>
</template> </template>
@@ -54,6 +51,14 @@ export default defineComponent({
type: String, type: String,
default: '', default: '',
}, },
selectType:{
type:String,
default:'single'
},
fieldTypes:{
type:Array,
default:()=>[]
},
hint: { hint: {
type: String, type: String,
default: '', default: '',

View File

@@ -1,10 +1,7 @@
<template> <template>
<div v-bind="$attrs"> <div v-bind="$attrs">
<q-input :label="displayName" v-model="inputValue" label-color="primary" <q-input :label="displayName" v-model="inputValue" label-color="primary" :placeholder="placeholder" stack-label
:placeholder="placeholder" stack-label :rules="rulesExp" :maxlength="maxLength">
:rules="rulesExp"
:maxlength="maxLength"
>
<template v-slot:append v-if="hint !== ''"> <template v-slot:append v-if="hint !== ''">
<q-icon name="help" size="22px" color="blue-8"> <q-icon name="help" size="22px" color="blue-8">
<q-tooltip class="bg-yellow-2 text-black shadow-4" anchor="bottom right"> <q-tooltip class="bg-yellow-2 text-black shadow-4" anchor="bottom right">
@@ -18,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import { kMaxLength } from 'buffer'; import { kMaxLength } from 'buffer';
import { defineComponent, ref, watchEffect } from 'vue'; import { defineComponent, ref, watchEffect, computed } from 'vue';
export default defineComponent({ export default defineComponent({
name: 'InputText', name: 'InputText',
@@ -36,31 +33,58 @@ export default defineComponent({
type: String, type: String,
default: '', default: '',
}, },
fieldTypes:{
type:Array,
default:()=>[]
},
hint: { hint: {
type: String, type: String,
default: '', default: '',
}, },
maxLength:{ maxLength: {
type: Number, type: Number,
default:undefined default: undefined
}, },
//例:[val=>!!val ||'入力してください'] //例:[val=>!!val ||'入力してください']
rules:{ rules: {
type:String, type: String,
default:undefined default: undefined
}, },
modelValue: { modelValue: {
type: String, // type: Any,
default: '', default: '',
}, },
}, },
setup(props, { emit }) { setup(props, { emit }) {
const inputValue = ref(props.modelValue); const inputValue = computed({
const rulesExp = props.rules===undefined?null : eval(props.rules); get: () => {
watchEffect(() => { if (props.modelValue !== null && typeof props.modelValue === 'object' && 'name' in props.modelValue) {
emit('update:modelValue', inputValue.value); return props.modelValue.name;
} else {
return props.modelValue;
}
},
set: (val) => {
if (props.name === 'verName') {
// return props.modelValue.name;
emit('update:modelValue', { name: val });
} else {
emit('update:modelValue', val);
}
},
}); });
// const inputValue = ref(props.modelValue);
const rulesExp = props.rules === undefined ? null : eval(props.rules);
// const finalValue = computed(() => {
// return props.name !== 'verName' ? inputValue.value : {
// name: inputValue.value,
// };
// });
// watchEffect(() => {
// emit('update:modelValue', finalValue);
// });
return { return {
inputValue, inputValue,

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div v-for="(item, index) in properties" :key="index" > <div v-for="(item, index) in properties" :key="index" >
<component :is="item.component" v-bind="item.props" :connectProps="connectProps(item.props)" v-model="item.props.modelValue"></component> <component :is="item.component" v-bind="item.props" :context="properties" :connectProps="connectProps(item.props)" v-model="item.props.modelValue"></component>
</div> </div>
</div> </div>
</template> </template>
@@ -21,6 +21,7 @@ import ConditionInput from '../right/ConditionInput.vue';
import EventSetter from '../right/EventSetter.vue'; import EventSetter from '../right/EventSetter.vue';
import ColorPicker from './ColorPicker.vue'; import ColorPicker from './ColorPicker.vue';
import NumInput from './NumInput.vue'; import NumInput from './NumInput.vue';
import DataProcessing from './DataProcessing.vue';
import { IActionNode,IActionProperty,IProp } from 'src/types/ActionTypes'; import { IActionNode,IActionProperty,IProp } from 'src/types/ActionTypes';
export default defineComponent({ export default defineComponent({
@@ -35,7 +36,8 @@ export default defineComponent({
ConditionInput, ConditionInput,
EventSetter, EventSetter,
ColorPicker, ColorPicker,
NumInput NumInput,
DataProcessing
}, },
props: { props: {
nodeProps: { nodeProps: {
@@ -50,7 +52,7 @@ export default defineComponent({
setup(props, context) { setup(props, context) {
const properties=ref(props.nodeProps); const properties=ref(props.nodeProps);
const connectProps=(props:IProp)=>{ const connectProps=(props:IProp)=>{
const connProps:any={}; const connProps:any={context:properties};
if(props && "connectProps" in props && props.connectProps!=undefined){ if(props && "connectProps" in props && props.connectProps!=undefined){
for(let connProp of props.connectProps){ for(let connProp of props.connectProps){
let targetProp = properties.value.find((prop)=>prop.props.name===connProp.propName); let targetProp = properties.value.find((prop)=>prop.props.name===connProp.propName);

View File

@@ -1,11 +1,12 @@
<template> <template>
<div v-bind="$attrs"> <div v-bind="$attrs">
<q-select v-model="selectedValue" :label="displayName" :options="options"/> <q-select v-model="selectedValue" :use-chips="multiple" :label="displayName" label-color="primary" :options="options" stack-label
:multiple="multiple"/>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent,ref,watchEffect } from 'vue'; import { defineComponent,ref,watchEffect,computed } from 'vue';
export default defineComponent({ export default defineComponent({
name: 'SelectBox', name: 'SelectBox',
@@ -23,20 +24,27 @@ export default defineComponent({
type: Array, type: Array,
required: true, required: true,
}, },
selectType:{
type:String,
default:'',
},
modelValue: { modelValue: {
type: String, type: [Array,String],
default: '', default: null,
}, },
}, },
setup(props, { emit }) { setup(props, { emit }) {
const selectedValue = ref(props.modelValue); const selectedValue = ref(props.modelValue);
const multiple = computed(()=>{
return props.selectType==='multiple'
});
watchEffect(() => { watchEffect(() => {
emit('update:modelValue', selectedValue.value); emit('update:modelValue', selectedValue.value);
}); });
return { return {
selectedValue selectedValue,
multiple
}; };
}, },
}); });

View File

@@ -1,44 +1,49 @@
import { api } from 'boot/axios'; import { api } from 'boot/axios';
import { ActionFlow } from 'src/types/ActionTypes'; import { ActionFlow } from 'src/types/ActionTypes';
export class FlowCtrl export class FlowCtrl {
{ async getFlows(appId: string): Promise<ActionFlow[]> {
const flows: ActionFlow[] = [];
async getFlows(appId:string):Promise<ActionFlow[]> try {
{ const result = await api.get(`api/flows/${appId}`);
const flows:ActionFlow[]=[]; //console.info(result.data);
try{ if (!result.data || !Array.isArray(result.data)) {
const result = await api.get(`api/flows/${appId}`); return [];
//console.info(result.data);
if(!result.data || !Array.isArray(result.data)){
return [];
}
for(const flow of result.data){
flows.push(ActionFlow.fromJSON(flow.content));
}
return flows;
}catch(error){
console.error(error);
return flows;
} }
for (const flow of result.data) {
flows.push(ActionFlow.fromJSON(flow.content));
}
return flows;
} catch (error) {
console.error(error);
return flows;
}
} }
async SaveFlow(jsonData:any):Promise<boolean> async SaveFlow(jsonData: any): Promise<boolean> {
{ const result = await api.post('api/flow', jsonData);
const result = await api.post('api/flow',jsonData); console.info(result.data);
console.info(result.data) return true;
return true;
} }
/** /**
* フローを更新する * フローを更新する
* @param jsonData * @param jsonData
* @returns * @returns
*/ */
async UpdateFlow(jsonData:any):Promise<boolean> async UpdateFlow(jsonData: any): Promise<boolean> {
{ const result = await api.put('api/flow/' + jsonData.flowid, jsonData);
const result = await api.put('api/flow/' + jsonData.flowid,jsonData); console.info(result.data);
console.info(result.data) return true;
}
/**
* フローを消去する
* @param flowId
* @returns
*/
async DeleteFlow(flowId: string): Promise<boolean> {
const result = await api.delete('api/flow/' + flowId);
console.info(result.data);
return true; return true;
} }
/** /**
@@ -46,12 +51,9 @@ export class FlowCtrl
* @param appid * @param appid
* @returns * @returns
*/ */
async depoly(appid:string):Promise<boolean> async depoly(appid: string): Promise<boolean> {
{
const result = await api.post(`api/v1/createjstokintone?app=${appid}`); const result = await api.post(`api/v1/createjstokintone?app=${appid}`);
console.info(result.data); console.info(result.data);
return true; return true;
} }
} }

View File

@@ -1,118 +1,142 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { AppInfo ,IActionFlow, IActionNode} from 'src/types/ActionTypes'; import { AppInfo, IActionFlow, IActionNode } from 'src/types/ActionTypes';
import { IKintoneEvent,KintoneEventManager } from 'src/types/KintoneEvents'; import { IKintoneEvent, KintoneEventManager } from 'src/types/KintoneEvents';
import {FlowCtrl } from '../control/flowctrl'; import { FlowCtrl } from '../control/flowctrl';
export interface FlowEditorState{ export interface FlowEditorState {
flowNames1:string; flowNames1: string;
appInfo?:AppInfo; appInfo?: AppInfo;
flows?:IActionFlow[]; flows?: IActionFlow[];
selectedFlow?:IActionFlow|undefined; selectedFlow?: IActionFlow | undefined;
activeNode:IActionNode|undefined; activeNode: IActionNode | undefined;
eventTree:KintoneEventManager; eventTree: KintoneEventManager;
selectedEvent:IKintoneEvent|undefined; selectedEvent: IKintoneEvent | undefined;
expandedScreen:any[]; expandedScreen: any[];
} }
const flowCtrl=new FlowCtrl(); const flowCtrl = new FlowCtrl();
const eventTree = new KintoneEventManager(); const eventTree = new KintoneEventManager();
export const useFlowEditorStore = defineStore("flowEditor",{ export const useFlowEditorStore = defineStore('flowEditor', {
state: ():FlowEditorState => ({ state: (): FlowEditorState => ({
flowNames1: '', flowNames1: '',
appInfo:undefined, appInfo: undefined,
flows:[], flows: [],
selectedFlow:undefined, selectedFlow: undefined,
activeNode:undefined, activeNode: undefined,
eventTree:eventTree, eventTree: eventTree,
selectedEvent:undefined, selectedEvent: undefined,
expandedScreen:[] expandedScreen: [],
}), }),
getters: { getters: {
/** /**
* *
* @returns 現在編集しているフロー * @returns 現在編集しているフロー
*/ */
currentFlow():IActionFlow|undefined{ currentFlow(): IActionFlow | undefined {
return this.selectedFlow; return this.selectedFlow;
}, },
/** /**
* KintoneイベントIDから、バンドしているフローを検索する * KintoneイベントIDから、バンドしているフローを検索する
* @param state * @param state
* @returns * @returns
*/ */
findFlowByEventId(state){ findFlowByEventId(state) {
return (eventId:string)=>{ return (eventId: string) => {
return state.flows?.find((flow)=>{ return state.flows?.find((flow) => {
const root=flow.getRoot(); const root = flow.getRoot();
return root?.name===eventId return root?.name === eventId;
}); });
} };
} },
findEventById(state) {
return (eventId: string) => {
return state.eventTree.findEventById(eventId);
};
},
}, },
actions: { actions: {
setFlows(flows:IActionFlow[]){ setFlows(flows: IActionFlow[]) {
this.flows=flows; this.flows = flows;
}, },
selectFlow(flow:IActionFlow){ selectFlow(flow: IActionFlow | undefined) {
this.selectedFlow=flow; this.selectedFlow = flow;
}, },
setActiveNode(node:IActionNode){ setActiveNode(node: IActionNode) {
this.activeNode=node; this.activeNode = node;
}, },
setApp(app:AppInfo){ setApp(app: AppInfo) {
this.appInfo=app; this.appInfo = app;
}, },
/** /**
* DBからフルーを保存する * DBからフルーを保存する
* @returns * @returns
*/ */
async loadFlow(){ async loadFlow() {
if(this.appInfo===undefined) return; if (this.appInfo === undefined) return;
const actionFlows = await flowCtrl.getFlows(this.appInfo?.appId); const actionFlows = await flowCtrl.getFlows(this.appInfo?.appId);
//eventTreeにバンドする //eventTreeにバンドする
this.eventTree.bindFlows(actionFlows); this.eventTree.bindFlows(actionFlows);
if(actionFlows===undefined || actionFlows.length===0){ if (actionFlows === undefined || actionFlows.length === 0) {
this.flows=[]; this.flows = [];
this.selectedFlow=undefined; this.selectedFlow = undefined;
return; return;
} }
this.setFlows(actionFlows); this.setFlows(actionFlows);
if(actionFlows && actionFlows.length>0){ if (actionFlows && actionFlows.length > 0) {
this.selectFlow(actionFlows[0]); this.selectFlow(actionFlows[0]);
} }
const expandNames = actionFlows.map(flow=>flow.getRoot()?.title); const expandNames = actionFlows.map((flow) => flow.getRoot()?.title);
// const expandName =actionFlows[0].getRoot()?.title; // const expandName =actionFlows[0].getRoot()?.title;
this.expandedScreen=expandNames; this.expandedScreen = expandNames;
}, },
/** /**
* フローをDBに保存及び更新する * フローをDBに保存及び更新する
*/ */
async saveFlow(flow:IActionFlow){ async saveFlow(flow: IActionFlow) {
const root=flow.getRoot(); const root = flow.getRoot();
const isNew = flow.id===''; const isNew = flow.id === '';
const jsonData={ const jsonData = {
flowid: isNew ? flow.createNewId():flow.id, flowid: isNew ? flow.createNewId() : flow.id,
appid: this.appInfo?.appId, appid: this.appInfo?.appId,
eventid: root?.name, eventid: root?.name,
name: root?.subTitle, name: root?.subTitle,
content: JSON.stringify(flow) content: JSON.stringify(flow),
} };
if(isNew){ if (isNew) {
return await flowCtrl.SaveFlow(jsonData); return await flowCtrl.SaveFlow(jsonData);
}else{ } else {
return await flowCtrl.UpdateFlow(jsonData); return await flowCtrl.UpdateFlow(jsonData);
} }
}, },
async deleteEvent(event: IKintoneEvent) {
const store = useFlowEditorStore();
if (event.flowData) {
const flow = event.flowData;
if (flow.id !== '') {
await flowCtrl.DeleteFlow(flow.id)
if (this.flows) {
this.flows = this.flows.filter((f) => f.id !== flow.id);
}
}
eventTree.deleteEvent(event, store);
}
else {
eventTree.deleteEvent(event, store);
}
},
/** /**
* デプロイする * デプロイする
*/ */
async deploy():Promise<boolean>{ async deploy(): Promise<boolean> {
if(this.appInfo===undefined){ if (this.appInfo === undefined) {
return false; return false;
} }
return await flowCtrl.depoly(this.appInfo?.appId); return await flowCtrl.depoly(this.appInfo?.appId);
} },
},
}
}); });

View File

@@ -45,7 +45,16 @@ export interface IActionProperty {
export interface IActionVariable{ export interface IActionVariable{
actionName:string; actionName:string;
displayName:string; displayName:string;
name:string; name: {
name:string;
actionName:string;
displayName:string;
vars : {
vName:string;
logicalOperator:string;
field: object;
}[]
};
} }
/** /**
* アクションタイプ定義 * アクションタイプ定義
@@ -448,6 +457,12 @@ export class ActionFlow implements IActionFlow {
getPrevVarNames(prevNode:IActionNode):IActionVariable[]{ getPrevVarNames(prevNode:IActionNode):IActionVariable[]{
let varNames:IActionVariable[]=[]; let varNames:IActionVariable[]=[];
if(prevNode.varName!==undefined && prevNode.varName.modelValue){ if(prevNode.varName!==undefined && prevNode.varName.modelValue){
if(prevNode.varName.modelValue ==='object'){
console.log(prevNode);
}
varNames.unshift({ varNames.unshift({
actionName:prevNode.name, actionName:prevNode.name,
displayName:prevNode.varName.displayName, displayName:prevNode.varName.displayName,

View File

@@ -198,7 +198,7 @@ export class ConditionTree {
if(value && typeof value ==='object' && ('label' in value)){ if(value && typeof value ==='object' && ('label' in value)){
value =condNode.value.label; value =condNode.value.label;
} }
return `${condNode.object.name} ${condNode.operator} '${value}'`; return `${typeof condNode.object.name === 'object' ? condNode.object.name.name : condNode.object.name} ${condNode.operator} '${value}'`;
} else { } else {
return ''; return '';
} }

View File

@@ -1,9 +1,10 @@
import {IActionFlow} from './ActionTypes'; import { useFlowEditorStore } from 'src/stores/flowEditor';
import { IActionFlow } from './ActionTypes';
export interface IKintoneEventNode { export interface IKintoneEventNode {
label: string; label: string;
header:string; header: string;
eventId:string; eventId: string;
parentId:string; parentId: string;
} }
export interface IKintoneEvent extends IKintoneEventNode { export interface IKintoneEvent extends IKintoneEventNode {
@@ -15,60 +16,64 @@ export interface IKintoneEventGroup extends IKintoneEventNode {
events: IKintoneEventNode[]; events: IKintoneEventNode[];
} }
export class kintoneEvent implements IKintoneEvent {
export class kintoneEvent implements IKintoneEvent{
eventId: string; eventId: string;
parentId:string; parentId: string;
get hasFlow(): boolean{ get hasFlow(): boolean {
return this.flowData!==undefined && this.flowData.actionNodes.length>1 return this.flowData !== undefined && this.flowData.actionNodes.length > 1;
}; }
flowData?: IActionFlow | undefined; flowData?: IActionFlow | undefined;
label: string; label: string;
get header():string{ header = 'EVENT';
return "EVENT"; constructor(label: string, eventId: string, parentId: string) {
} this.eventId = eventId;
constructor(label:string,eventId:string,parentId:string){ this.label = label;
this.eventId=eventId; this.parentId = parentId;
this.label=label;
this.parentId=parentId;
} }
} }
export class kintoneEventGroup implements IKintoneEventGroup{ export class kintoneEventGroup implements IKintoneEventGroup {
eventId: string; eventId: string;
parentId:string; parentId: string;
label: string; label: string;
events: IKintoneEventNode[]; events: IKintoneEventNode[];
get header():string{ get header(): string {
return "EVENTGROUP"; return 'EVENTGROUP';
} }
constructor(eventId:string,label:string,events:IKintoneEventNode[],parentId:string){ constructor(
this.eventId=eventId; eventId: string,
this.label=label; label: string,
this.events=events; events: IKintoneEventNode[],
this.parentId=parentId; parentId: string
) {
this.eventId = eventId;
this.label = label;
this.events = events;
this.parentId = parentId;
} }
} }
export class kintoneEventForChange implements IKintoneEventGroup {
export class kintoneEventForChange implements IKintoneEventGroup{
eventId: string; eventId: string;
parentId:string; parentId: string;
label: string; label: string;
events: IKintoneEventNode[]; events: IKintoneEventNode[];
get header():string{ get header(): string {
return "CHANGE"; return 'CHANGE';
} }
constructor(eventId:string,label:string,events:IKintoneEventNode[],parentId:string){ constructor(
this.eventId=eventId; eventId: string,
this.label=label; label: string,
this.events=events; events: IKintoneEventNode[],
this.parentId=parentId; parentId: string
) {
this.eventId = eventId;
this.label = label;
this.events = events;
this.parentId = parentId;
} }
} }
export class KintoneEventManager { export class KintoneEventManager {
public screens: IKintoneEventGroup[]; public screens: IKintoneEventGroup[];
@@ -76,28 +81,32 @@ export class KintoneEventManager {
this.screens = this.getKintoneEvents(); this.screens = this.getKintoneEvents();
} }
public bindFlows(flows:IActionFlow[]){ public bindFlows(flows: IActionFlow[]) {
this.screens=this.getKintoneEvents(); this.screens = this.getKintoneEvents();
for (const flow of flows){ for (const flow of flows) {
const eventId =flow.getRoot()?.name; const eventId = flow.getRoot()?.name;
if(eventId!==undefined){ if (eventId !== undefined) {
const eventNode = this.findEventById(eventId); const eventNode = this.findEventById(eventId);
if(eventNode!==null && eventNode.header==="EVENT"){ if (eventNode !== null && eventNode.header === 'EVENT') {
const event =eventNode as kintoneEvent; const event = eventNode as kintoneEvent;
event.flowData=flow; event.flowData = flow;
}else{ } else {
//EventGroupのIDを取得 //EventGroupのIDを取得
const lastIndex = eventId.lastIndexOf("."); const lastIndex = eventId.lastIndexOf('.');
const groupId=eventId.substring(0,lastIndex); const groupId = eventId.substring(0, lastIndex);
const eventNode = this.findEventById(groupId); const eventNode = this.findEventById(groupId);
if(eventNode && (eventNode.header==="EVENTGROUP" || eventNode.header==="CHANGE")){ if (eventNode && (eventNode.header === 'EVENTGROUP' || eventNode.header === 'CHANGE')) {
const groupEvent=eventNode as kintoneEventGroup; const groupEvent = eventNode as kintoneEventGroup;
const newEvent =new kintoneEvent(
flow.getRoot()?.subTitle || "", const newEvent = {
eventId, label: flow.getRoot()?.subTitle || '',
groupEvent.parentId eventId: eventId,
); parentId: groupId,
newEvent.flowData=flow; header: 'DELETABLE',
hasFlow: true,
flowData: flow,
};
groupEvent.events.push(newEvent); groupEvent.events.push(newEvent);
} }
} }
@@ -106,61 +115,193 @@ export class KintoneEventManager {
} }
public findEventById(eventId: string): IKintoneEventNode | null { public findEventById(eventId: string): IKintoneEventNode | null {
const screen=this.findScreen(eventId); const screen = this.findScreen(eventId);
if(screen) {return screen;} if (screen) {
return screen;
}
for (const screen of this.screens) { for (const screen of this.screens) {
for (const event of screen.events) { for (const event of screen.events) {
if (event.eventId === eventId) { if (event.eventId === eventId) {
return event; return event;
} }
if(event.header==="EVENTGROUP"||event.header==="CHANGE"){ if (event.header === 'EVENTGROUP' || event.header === 'CHANGE') {
const eventGroup = event as IKintoneEventGroup; const eventGroup = event as IKintoneEventGroup;
const targetEvent = eventGroup.events.find((ev)=>{ const targetEvent = eventGroup.events.find((ev) => {
return ev.eventId===eventId; return ev.eventId === eventId;
}) });
if(targetEvent){ if (targetEvent) {
return targetEvent; return targetEvent;
}
} }
}
} }
} }
return null; return null;
} }
public findScreen(eventId:string):IKintoneEventGroup|undefined{ public findScreen(eventId: string): IKintoneEventGroup | undefined {
return this.screens.find(screen=>screen.eventId==eventId); return this.screens.find((screen) => screen.eventId == eventId);
} }
public getKintoneEvents():IKintoneEventGroup[]{ public deleteEvent(
event: kintoneEvent,
store: ReturnType<typeof useFlowEditorStore>
) {
if (event.header !== 'DELETABLE') {
return;
}
const parent = store.findEventById(event.parentId);
if (parent?.header !== 'CHANGE' && parent?.header !== 'EVENTGROUP') {
return;
}
const realParent = parent as kintoneEventForChange;
const index = realParent.events.findIndex(
(e) => e.eventId === event.eventId
);
if (index !== -1) {
realParent.events.splice(index, 1);
}
}
public getKintoneEvents(): IKintoneEventGroup[] {
return [ return [
new kintoneEventGroup("app.record.create","レコード追加画面",[ new kintoneEventGroup(
new kintoneEvent('レコード追加画面を表示した後','app.record.create.show',"app.record.create"), 'app.record.create',
new kintoneEvent('保存をクリックしたとき','app.record.create.submit',"app.record.create"), 'レコード追加画面',
new kintoneEvent('保存が成功したとき','app.record.create.submit.success',"app.record.create"), [
new kintoneEventForChange('app.record.create.change','フィールドの値を変更したとき',[],"app.record.create"), new kintoneEvent(
new kintoneEventGroup('app.record.create.show.customButtonClick','ボタンをクリックした',[],"app.record.create") 'レコード追加画面を表示した',
],""), 'app.record.create.show',
new kintoneEventGroup("app.record.detail","レコード詳細画面",[ 'app.record.create'
new kintoneEvent('レコード詳細画面を表示した後','app.record.detail.show',"app.record.detail"), ),
new kintoneEvent('レコードを削除するとき','app.record.detail.delete.submit',"app.record.detail"), new kintoneEvent(
new kintoneEvent('プロセス管理のアクションを実行したとき','app.record.detail.process.proceed',"app.record.detail"), '保存をクリックしたとき',
new kintoneEventGroup('app.record.detail.show.customButtonClick','ボタンをクリックした時',[],"app.record.detail"), 'app.record.create.submit',
],""), 'app.record.create'
new kintoneEventGroup("app.record.edit","レコード編集画面",[ ),
new kintoneEvent('レコード編集画面を表示した後','app.record.edit.show',"app.record.edit"), new kintoneEvent(
new kintoneEvent('保存をクリックしたとき','app.record.edit.submit',"app.record.edit"), '保存が成功したとき',
new kintoneEvent('保存が成功したとき','app.record.edit.submit.success',"app.record.edit"), 'app.record.create.submit.success',
new kintoneEventForChange('app.record.edit.change','フィールドの値を変更したとき',[],"app.record.edit"), 'app.record.create'
new kintoneEventGroup('app.record.edit.show.customButtonClick','ボタンをクリックした時',[],"app.record.edit"), ),
],""), new kintoneEventForChange(
new kintoneEventGroup("app.record.index","レコード一覧画面",[ 'app.record.create.change',
new kintoneEvent('一覧画面を表示した後', 'app.record.index.show',"app.record.index"), 'フィールドの値を変更したとき',
new kintoneEvent('インライン編集を開始したとき','app.record.index.edit.show',"app.record.index"), [],
new kintoneEvent('インライン編集の【保存】をクリックしたとき','app.record.index.edit.submit',"app.record.index"), 'app.record.create'
new kintoneEvent('インライン編集の保存が成功したとき', 'app.record.index.edit.submit.success',"app.record.index"), ),
new kintoneEventForChange('app.record.index.edit.change','インライン編集のフィールド値を変更したとき' ,[],"app.record.index"), new kintoneEventGroup(
new kintoneEventGroup('app.record.detail.show.customButtonClick','ボタンをクリックした時',[],"app.record.index"), 'app.record.create.show.customButtonClick',
],"") 'ボタンをクリックした時',
[],
'app.record.create'
),
],
''
),
new kintoneEventGroup(
'app.record.detail',
'レコード詳細画面',
[
new kintoneEvent(
'レコード詳細画面を表示した後',
'app.record.detail.show',
'app.record.detail'
),
new kintoneEvent(
'レコードを削除するとき',
'app.record.detail.delete.submit',
'app.record.detail'
),
new kintoneEvent(
'プロセス管理のアクションを実行したとき',
'app.record.detail.process.proceed',
'app.record.detail'
),
new kintoneEventGroup(
'app.record.detail.show.customButtonClick',
'ボタンをクリックした時',
[],
'app.record.detail'
),
],
''
),
new kintoneEventGroup(
'app.record.edit',
'レコード編集画面',
[
new kintoneEvent(
'レコード編集画面を表示した後',
'app.record.edit.show',
'app.record.edit'
),
new kintoneEvent(
'保存をクリックしたとき',
'app.record.edit.submit',
'app.record.edit'
),
new kintoneEvent(
'保存が成功したとき',
'app.record.edit.submit.success',
'app.record.edit'
),
new kintoneEventForChange(
'app.record.edit.change',
'フィールドの値を変更したとき',
[],
'app.record.edit'
),
new kintoneEventGroup(
'app.record.edit.show.customButtonClick',
'ボタンをクリックした時',
[],
'app.record.edit'
),
],
''
),
new kintoneEventGroup(
'app.record.index',
'レコード一覧画面',
[
new kintoneEvent(
'一覧画面を表示した後',
'app.record.index.show',
'app.record.index'
),
new kintoneEvent(
'インライン編集を開始したとき',
'app.record.index.edit.show',
'app.record.index'
),
new kintoneEvent(
'インライン編集の【保存】をクリックしたとき',
'app.record.index.edit.submit',
'app.record.index'
),
new kintoneEvent(
'インライン編集の保存が成功したとき',
'app.record.index.edit.submit.success',
'app.record.index'
),
new kintoneEventForChange(
'app.record.index.edit.change',
'インライン編集のフィールド値を変更したとき',
[],
'app.record.index'
),
new kintoneEventGroup(
'app.record.detail.show.customButtonClick',
'ボタンをクリックした時',
[],
'app.record.index'
),
],
''
),
]; ];
} }
} }

View File

@@ -6,20 +6,23 @@
"scripts": { "scripts": {
"dev": "tsc && set \"SOURCE_MAP=true\" && vite build && vite preview", "dev": "tsc && set \"SOURCE_MAP=true\" && vite build && vite preview",
"build": "tsc && vite build && xcopy dist\\*.js ..\\..\\backend\\Temp\\ /E /I /Y", "build": "tsc && vite build && xcopy dist\\*.js ..\\..\\backend\\Temp\\ /E /I /Y",
"build:linux": "tsc && vite build && cp -ur dist/*.js ../../backend/Temp",
"build:dev": "tsc && set \"SOURCE_MAP=true\" && vite build && xcopy dist\\*.js ..\\..\\backend\\Temp\\ /E /I /Y", "build:dev": "tsc && set \"SOURCE_MAP=true\" && vite build && xcopy dist\\*.js ..\\..\\backend\\Temp\\ /E /I /Y",
"preview": "vite preview", "preview": "vite preview",
"ngrok":"ngrok http http://localhost:4173/", "ngrok": "ngrok http http://localhost:4173/",
"vite":"vite dev" "vite": "vite dev"
}, },
"devDependencies": { "devDependencies": {
"@types/jquery": "^3.5.24", "@types/jquery": "^3.5.24",
"@types/node": "^20.8.9", "@types/node": "^20.8.9",
"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"
}, },
"dependencies": { "dependencies": {
"jquery": "^3.7.1", "jquery": "^3.7.1",
"vite-plugin-css-injected-by-js": "^3.5.1",
"yarn": "^1.22.22" "yarn": "^1.22.22"
} }
} }

View File

@@ -84,6 +84,7 @@ export class AutoNumbering implements IAction{
execEval(match:string,expr:string):string{ execEval(match:string,expr:string):string{
console.log(match); console.log(match);
// @ts-ignore
return eval(expr); return eval(expr);
} }

View File

@@ -0,0 +1,24 @@
.alc-button-normal {
display: inline-block;
box-sizing: border-box;
padding: 0 16px;
margin-left: 16px;
margin-top: 8px;
min-width: 100px;
outline: none;
border: 1px solid #e3e7e8;
background-color: #f7f9fa;
box-shadow: 1px 1px 1px #fff inset;
color: #3498db;
text-align: center;
line-height: 32px;
}
.alc-button-normal:hover {
background-color: #c8d6dd;
box-shadow: none;
cursor: pointer;
}
.alc-button-normal:active {
color: #f7f9fa;
background-color: #54b8eb;
}

View File

@@ -2,16 +2,24 @@
import { actionAddins } from "."; import { actionAddins } from ".";
import $ from 'jquery'; import $ from 'jquery';
import { IAction, IActionProperty, IActionNode, IActionResult } from "../types/ActionTypes"; import { IAction, IActionProperty, IActionNode, IActionResult } from "../types/ActionTypes";
import "./button-add.css";
/** /**
* ボタン配置属性定義 * ボタン配置属性定義
*/ */
interface IButtonAddProps { interface IButtonAddProps {
//ボタン表示名 //ボタン表示名
buttonName: string; buttonName: string;
space?:ISpace;
//配置位置 //配置位置
position: string; position: string;
//イベント名 //イベント名
eventName:string eventName:string
}
interface ISpace{
type:string,
elementId:string
} }
export class ButtonAddAction implements IAction { export class ButtonAddAction implements IAction {
@@ -47,43 +55,19 @@ export class ButtonAddAction implements IAction {
} }
this.props = actionNode.ActionValue as IButtonAddProps; this.props = actionNode.ActionValue as IButtonAddProps;
//ボタンを配置する //ボタンを配置する
const menuSpace = kintone.app.record.getHeaderMenuSpaceElement(); let buttonSpace;
if(!menuSpace) return result; if(this.props.space && this.props.space.elementId){
if($("style#alc-button-add").length===0){ buttonSpace = kintone.app.record.getSpaceElement(this.props.space.elementId);
const css=` }else{
.alc-button-normal { buttonSpace = kintone.app.record.getHeaderMenuSpaceElement();
display: inline-block;
box-sizing: border-box;
padding: 0 16px;
margin-left: 16px;
margin-top: 8px;
min-width: 100px;
outline: none;
border: 1px solid #e3e7e8;
background-color: #f7f9fa;
box-shadow: 1px 1px 1px #fff inset;
color: #3498db;
text-align: center;
line-height: 32px;
}
.alc-button-normal:hover {
background-color: #c8d6dd;
box-shadow: none;
cursor: pointer;
}
.alc-button-normal:active {
color: #f7f9fa;
background-color: #54b8eb;
}`;
const style = $("<style id='alc-button-add'>/<style>");
style.text(css);
$("head").append(style);
} }
if(!buttonSpace) return result;
const button =$(`<button id='${this.props.eventName}' class='alc-button-normal' >${this.props.buttonName}</button>`); const button =$(`<button id='${this.props.eventName}' class='alc-button-normal' >${this.props.buttonName}</button>`);
if(this.props.position==="一番左に追加する"){ if(this.props.position==="一番左に追加する"){
$(menuSpace).prepend(button); $(buttonSpace).prepend(button);
}else{ }else{
$(menuSpace).append(button); $(buttonSpace).append(button);
} }
const clickEventName = `${event.type}.customButtonClick.${this.props.eventName}`; const clickEventName = `${event.type}.customButtonClick.${this.props.eventName}`;
button.on("click",()=>{ button.on("click",()=>{
@@ -97,6 +81,7 @@ export class ButtonAddAction implements IAction {
return result; return result;
} }
} }
register(): void { register(): void {
actionAddins[this.name] = this; actionAddins[this.name] = this;

View File

@@ -1,8 +1,11 @@
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";
import { ConditionTree } from '../types/Conditions'; import { ConditionTree } from '../types/Conditions';
/** /**
* アクションの属性定義 * アクションの属性定義
*/ */
@@ -353,11 +356,11 @@ export class InsertValueAction implements IAction{
let correctFormattedValue; let correctFormattedValue;
//入力値チェック後、形式変換、型変換した値を格納する配列 //入力値チェック後、形式変換、型変換した値を格納する配列
let correctValues :string[] = []; let correctValues :string[] = [];
//空白文字チェックの結果が負の場合、true //入力エラー(空白文字の混入)がないことをチェック
let checkInputError=this.checkInputBlank(fieldType,fieldValue,fieldCode,fieldRequired,event); let notInputError=this.checkInputBlank(fieldType,fieldValue,fieldCode,fieldRequired,event);
//条件式の結果がtrue、空白文字チェックでエラーがない場合、挿入する値をフィールドタイプ別にチェックする //条件式の結果がtrue、入力エラー(空白文字の混入)がない場合、挿入する値をフィールドタイプ別にチェックする
if(conditionResult && !checkInputError){ if(conditionResult && notInputError){
//文字列型のフィールドに挿入しようとしている値が適切の場合、correctFormattedValueに代入する //文字列型のフィールドに挿入しようとしている値が適切の場合、correctFormattedValueに代入する
if(fieldType === "SINGLE_LINE_TEXT" || fieldType === "MULTI_LINE_TEXT" || fieldType === "RICH_TEXT" || fieldType === "LINK" ){ if(fieldType === "SINGLE_LINE_TEXT" || fieldType === "MULTI_LINE_TEXT" || fieldType === "RICH_TEXT" || fieldType === "LINK" ){

View File

@@ -1,9 +1,3 @@
// export const sum = (a: number, b: number) => {
// if ('development' === process.env.NODE_ENV) {
// console.log('boop');
// }
// return a + b;
// };
import $ from 'jquery'; import $ from 'jquery';
import { ActionProcess } from './types/action-process'; import { ActionProcess } from './types/action-process';
import { ActionFlow } from './types/ActionTypes'; import { ActionFlow } from './types/ActionTypes';

View File

@@ -1,16 +1,26 @@
// vite.config.js // vite.config.js
import { defineConfig } from 'vite' import { defineConfig } from "vite";
const sourcemap = process.env.SOURCE_MAP==='true'; import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
import checker from "vite-plugin-checker";
const sourcemap = process.env.SOURCE_MAP === "true";
export default defineConfig({ export default defineConfig({
plugins: [
checker({
typescript: true,
}),
cssInjectedByJsPlugin(),
],
build: { build: {
cssCodeSplit: false,
rollupOptions: { rollupOptions: {
input: 'src/index.ts', // entry file input: "src/index.ts", // entry file
output:{ output: {
entryFileNames:'alc_runtime.js', entryFileNames: "alc_runtime.js",
// assetFileNames:'alc_kintone_style.css' // assetFileNames:'alc_kintone_style.css'
} },
}, },
sourcemap:sourcemap sourcemap: sourcemap,
} },
}) });

View File

@@ -2,6 +2,29 @@
# yarn lockfile v1 # yarn lockfile v1
"@babel/code-frame@^7.12.13":
version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465"
integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==
dependencies:
"@babel/highlight" "^7.24.7"
picocolors "^1.0.0"
"@babel/helper-validator-identifier@^7.24.7":
version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db"
integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
"@babel/highlight@^7.24.7":
version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d"
integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==
dependencies:
"@babel/helper-validator-identifier" "^7.24.7"
chalk "^2.4.2"
js-tokens "^4.0.0"
picocolors "^1.0.0"
"@esbuild/android-arm64@0.18.20": "@esbuild/android-arm64@0.18.20":
version "0.18.20" version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622"
@@ -112,6 +135,27 @@
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==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
dependencies:
"@nodelib/fs.stat" "2.0.5"
run-parallel "^1.1.9"
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
"@nodelib/fs.walk@^1.2.3":
version "1.2.8"
resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
dependencies:
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@types/jquery@^3.5.24": "@types/jquery@^3.5.24":
version "3.5.24" version "3.5.24"
resolved "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.24.tgz" resolved "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.24.tgz"
@@ -131,6 +175,32 @@
resolved "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.5.tgz" resolved "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.5.tgz"
integrity sha512-tAe4Q+OLFOA/AMD+0lq8ovp8t3ysxAOeaScnfNdZpUxaGl51ZMDEITxkvFl1STudQ58mz6gzVGl9VhMKhwRnZQ== integrity sha512-tAe4Q+OLFOA/AMD+0lq8ovp8t3ysxAOeaScnfNdZpUxaGl51ZMDEITxkvFl1STudQ58mz6gzVGl9VhMKhwRnZQ==
ansi-escapes@^4.3.0:
version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
dependencies:
type-fest "^0.21.3"
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
dependencies:
color-convert "^1.9.0"
ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
anymatch@~3.1.2: anymatch@~3.1.2:
version "3.1.3" version "3.1.3"
resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz"
@@ -139,11 +209,31 @@ anymatch@~3.1.2:
normalize-path "^3.0.0" normalize-path "^3.0.0"
picomatch "^2.0.4" picomatch "^2.0.4"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
binary-extensions@^2.0.0: binary-extensions@^2.0.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
braces@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
dependencies:
fill-range "^7.1.1"
braces@~3.0.2: braces@~3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz"
@@ -151,6 +241,23 @@ braces@~3.0.2:
dependencies: dependencies:
fill-range "^7.0.1" fill-range "^7.0.1"
chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^4.1.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
"chokidar@>=3.0.0 <4.0.0": "chokidar@>=3.0.0 <4.0.0":
version "3.5.3" version "3.5.3"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
@@ -166,6 +273,55 @@ braces@~3.0.2:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
chokidar@^3.5.1:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
dependencies:
color-name "1.1.3"
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
dependencies:
color-name "~1.1.4"
color-name@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
commander@^8.0.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
esbuild@^0.18.10: esbuild@^0.18.10:
version "0.18.20" version "0.18.20"
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz"
@@ -194,6 +350,29 @@ esbuild@^0.18.10:
"@esbuild/win32-ia32" "0.18.20" "@esbuild/win32-ia32" "0.18.20"
"@esbuild/win32-x64" "0.18.20" "@esbuild/win32-x64" "0.18.20"
escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
fast-glob@^3.2.7:
version "3.3.2"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
dependencies:
"@nodelib/fs.stat" "^2.0.2"
"@nodelib/fs.walk" "^1.2.3"
glob-parent "^5.1.2"
merge2 "^1.3.0"
micromatch "^4.0.4"
fastq@^1.6.0:
version "1.17.1"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47"
integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==
dependencies:
reusify "^1.0.4"
fill-range@^7.0.1: fill-range@^7.0.1:
version "7.0.1" version "7.0.1"
resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz"
@@ -201,18 +380,49 @@ fill-range@^7.0.1:
dependencies: dependencies:
to-regex-range "^5.0.1" to-regex-range "^5.0.1"
fill-range@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"
fs-extra@^11.1.0:
version "11.2.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b"
integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^6.0.1"
universalify "^2.0.0"
fsevents@~2.3.2: fsevents@~2.3.2:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
glob-parent@~5.1.2: glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2" version "5.1.2"
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies: dependencies:
is-glob "^4.0.1" is-glob "^4.0.1"
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
immutable@^4.0.0: immutable@^4.0.0:
version "4.3.4" version "4.3.4"
resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz" resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz"
@@ -247,6 +457,40 @@ jquery@^3.7.1:
resolved "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz" resolved "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz"
integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
dependencies:
universalify "^2.0.0"
optionalDependencies:
graceful-fs "^4.1.6"
merge2@^1.3.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
micromatch@^4.0.4:
version "4.0.7"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5"
integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==
dependencies:
braces "^3.0.3"
picomatch "^2.3.1"
minimatch@^3.0.4:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
dependencies:
brace-expansion "^1.1.7"
nanoid@^3.3.6: nanoid@^3.3.6:
version "3.3.6" version "3.3.6"
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz"
@@ -257,12 +501,24 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
npm-run-path@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
dependencies:
path-key "^3.0.0"
path-key@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
picocolors@^1.0.0: picocolors@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
picomatch@^2.0.4, picomatch@^2.2.1: picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
version "2.3.1" version "2.3.1"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@@ -276,6 +532,11 @@ postcss@^8.4.27:
picocolors "^1.0.0" picocolors "^1.0.0"
source-map-js "^1.0.2" source-map-js "^1.0.2"
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
readdirp@~3.6.0: readdirp@~3.6.0:
version "3.6.0" version "3.6.0"
resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz"
@@ -283,6 +544,11 @@ readdirp@~3.6.0:
dependencies: dependencies:
picomatch "^2.2.1" picomatch "^2.2.1"
reusify@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rollup@^3.27.1: rollup@^3.27.1:
version "3.29.4" version "3.29.4"
resolved "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz" resolved "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz"
@@ -290,6 +556,13 @@ rollup@^3.27.1:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
dependencies:
queue-microtask "^1.2.2"
sass@^1.69.5: sass@^1.69.5:
version "1.69.7" version "1.69.7"
resolved "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz" resolved "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz"
@@ -299,11 +572,42 @@ sass@^1.69.5:
immutable "^4.0.0" immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0" source-map-js ">=0.6.2 <2.0.0"
semver@^7.3.4, semver@^7.5.0:
version "7.6.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
strip-ansi@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
dependencies:
has-flag "^3.0.0"
supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"
tiny-invariant@^1.1.0:
version "1.3.3"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==
to-regex-range@^5.0.1: to-regex-range@^5.0.1:
version "5.0.1" version "5.0.1"
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
@@ -311,6 +615,11 @@ to-regex-range@^5.0.1:
dependencies: dependencies:
is-number "^7.0.0" is-number "^7.0.0"
type-fest@^0.21.3:
version "0.21.3"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
typescript@^5.0.2: typescript@^5.0.2:
version "5.2.2" version "5.2.2"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz" resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz"
@@ -321,6 +630,37 @@ undici-types@~5.26.4:
resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
universalify@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"
integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==
vite-plugin-checker@^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/vite-plugin-checker/-/vite-plugin-checker-0.6.4.tgz#aca186ab605aa15bd2c5dd9cc6d7c8fdcbe214ec"
integrity sha512-2zKHH5oxr+ye43nReRbC2fny1nyARwhxdm0uNYp/ERy4YvU9iZpNOsueoi/luXw5gnpqRSvjcEPxXbS153O2wA==
dependencies:
"@babel/code-frame" "^7.12.13"
ansi-escapes "^4.3.0"
chalk "^4.1.1"
chokidar "^3.5.1"
commander "^8.0.0"
fast-glob "^3.2.7"
fs-extra "^11.1.0"
npm-run-path "^4.0.1"
semver "^7.5.0"
strip-ansi "^6.0.0"
tiny-invariant "^1.1.0"
vscode-languageclient "^7.0.0"
vscode-languageserver "^7.0.0"
vscode-languageserver-textdocument "^1.0.1"
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@^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"
@@ -332,6 +672,50 @@ vite@^4.4.5:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
vscode-jsonrpc@6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e"
integrity sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==
vscode-languageclient@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz#b505c22c21ffcf96e167799757fca07a6bad0fb2"
integrity sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==
dependencies:
minimatch "^3.0.4"
semver "^7.3.4"
vscode-languageserver-protocol "3.16.0"
vscode-languageserver-protocol@3.16.0:
version "3.16.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz#34135b61a9091db972188a07d337406a3cdbe821"
integrity sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==
dependencies:
vscode-jsonrpc "6.0.0"
vscode-languageserver-types "3.16.0"
vscode-languageserver-textdocument@^1.0.1:
version "1.0.11"
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz#0822a000e7d4dc083312580d7575fe9e3ba2e2bf"
integrity sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==
vscode-languageserver-types@3.16.0:
version "3.16.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247"
integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==
vscode-languageserver@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz#49b068c87cfcca93a356969d20f5d9bdd501c6b0"
integrity sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==
dependencies:
vscode-languageserver-protocol "3.16.0"
vscode-uri@^3.0.2:
version "3.0.8"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f"
integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==
yarn@^1.22.22: yarn@^1.22.22:
version "1.22.22" version "1.22.22"
resolved "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz" resolved "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz"