Compare commits

..

71 Commits

Author SHA1 Message Date
7690a62ad4 get_eventactions bugfix 2024-06-25 00:24:01 +09:00
ded1222003 eventaction テーブル変更 eventid(event.id->event.eventid) 2024-06-24 14:46:09 +09:00
Kanaru Tsuda
26a685b872 Merged PR 39: feat 236(全角チェック),284(半角チェック)
コンポーネントの改修

Related work items: #236, #284
2024-06-13 06:32:02 +00:00
Shohtetsu Ma
8514adf15e Merged PR 40: 変数定義の型はstring->IVarNameへ変更
変数定義の型を変更しました。
今後変数はオブジェクト型を対応可能のため、インターフェースを変更しました
下記のアクションを対応しました。
・auto-numbering.ts
・datetime-getter.ts
・value-getter.ts
・condition-action.ts
2024-06-13 06:31:23 +00:00
kanarutsuda
5f2059fd6a feat 236,284 全半角の改修コミット 2024-06-13 15:20:04 +09:00
504a76b4ac feat:変数定義類型の変更対応 2024-06-13 15:16:44 +09:00
kanarutsuda
80694ee49c feat 236,284 全半角のチェック コミット 2024-06-13 15:12:30 +09:00
kanarutsuda
493b9ca0e9 Merge branch 'dev' into feature/validation-half-width 2024-06-13 15:04:20 +09:00
kanarutsuda
55bbf50656 feat 236,284
全半角の改修コミット
2024-06-13 14:51:28 +09:00
4b27504b99 bugfix:フィールド表示障害修正 2024-06-13 13:53:43 +09:00
kanarutsuda
1d248bde43 半角チェック文字コード修正変更 2024-06-12 17:34:13 +09:00
Kanaru Tsuda
5cad10575f Merged PR 38: 半角チェック、全角チェックファイル名変更
それぞれfull widthcheck,half widthcheckをfull-widthcheck,half-widthcheckに変更しました

Related work items: #380
2024-06-12 07:39:58 +00:00
kanarutsuda
3b56c78bf1 ファイル名変更(削除) 2024-06-12 16:37:14 +09:00
kanarutsuda
6ab668f86a ファイル名の変更 2024-06-12 16:13:32 +09:00
kanarutsuda
7b1daaab33 ファイル名の変更 2024-06-12 15:55:38 +09:00
kanarutsuda
ef47912c37 feat: #380 半角チェック
指定したフィールドが半角かどうか判定する(全角が1文字でも含まれていたらエラー表示)
2024-06-12 15:25:50 +09:00
Shohtetsu Ma
140c48bcb7 Merged PR 36: 属性UIの新機能追加
1.フィールド選択UIのフィールド種別指定追加
2.スペースにボタン配置可能にする
3.選択肢UIの複数選択可能にする
4.スペース表示するため、バックエンドの改修
5.ボタンクリックイベントと項目値変更イベントのノード削除機能追加

Related work items: #241, #316, #344
2024-06-11 10:32:54 +00:00
ba0b96146e merge:DEVブランチとマージする 2024-06-11 19:22:05 +09:00
53aa5dff88 env:環境ファイル戻す 2024-06-11 18:21:18 +09:00
e52b02ec7f bugfix:アプリフィールド選択のフィールド種別指定修正 2024-06-11 18:10:04 +09:00
47dbaaf87d 環境変数戻す 2024-06-11 17:16:51 +09:00
478c751ea7 ボタン配置改修 2024-06-11 15:14:31 +09:00
4ee72a8a75 ボタン配置改修 2024-06-11 15:11:24 +09:00
Yukina Mori
e2db112080 Merged PR 33: fix: #234 フィールドに値を挿入するコンポーネントのinsert-value.tsの修正
fix: #234 フィールドに値を挿入するコンポーネントのinsert-value.tsの修正

コンポーネントの動作確認が取れていなかったため、insert-value.tsを修正いたしました。

Related work items: #234
2024-06-11 05:05:41 +00:00
Moriyukina2
3c0d572a0e fix: #234 フィールドに値を挿入するコンポーネントのinsert-value.tsのコメントの修正 2024-06-11 13:58:19 +09:00
Moriyukina2
c225ddd39d fix: #234 フィールドに値を挿入するコンポーネントのinsert-value.tsの修正
コンポーネントの動作確認が取れていなかったため、insert-value.tsを修正いたしました。
2024-06-11 13:19:17 +09:00
0e9b0ea693 feat:タブ対応するためにボタン配置対応 2024-06-11 09:57:52 +09:00
36f225a5b6 Merge remote-tracking branch 'origin/feature-delete-event' into feature/button-on-space 2024-06-11 02:24:10 +09:00
9496128e02 Merge branch 'feature-data-processing' into feature/button-on-space 2024-06-10 11:41:52 +09:00
612962cc83 merge with dev 2024-06-10 11:33:42 +09:00
52514b7197 feat:ボタンをスペースに配置 2024-06-10 11:24:10 +09:00
Kanaru Tsuda
234e55bc01 Merged PR 32: 全角チェック
指定したフィールドが全角かどうかをチェックし、全角でなければエラーを出す。
2024-06-05 06:05:07 +00:00
kanarutsuda
f4a1bc3e58 Merge remote-tracking branch 'origin/dev' into feature/full-width-check 2024-06-05 13:26:29 +09:00
Kanaru Tsuda
192174b2ca Deleted fullwidth-check.ts 2024-06-04 05:45:02 +00:00
kanarutsuda
544370688e 全角チェックのアップデート 2024-06-04 14:35:11 +09:00
Yu Wang
6a6e772e32 Merged PR 29: feat:#239文字結合コンポーネントの追加
文字結合コンポーネントの追加

Related work items: #239
2024-06-03 09:48:31 +00:00
tenraku ou
f4500a09bc Merged PR 28: 追加 フィールドの値を取得する
追加 フィールドの値を取得する

Related work items: #287
2024-06-03 09:46:32 +00:00
takuto
e7c3d3c8ad merge:action-processの整備 2024-06-03 18:30:30 +09:00
王玉
91bd72f7e0 feat:#239文字結合コンポーネントの追加,action-process onflict改修 2024-06-03 17:59:34 +09:00
王玉
2e69dc4dcf feat:#239文字結合コンポーネントの追加 2024-06-03 17:39:54 +09:00
tenraku ou
535049a188 Updated action-process.ts 2024-06-03 07:41:33 +00:00
tenraku ou
5bde55e5fc Updated value-getter.ts 2024-06-03 07:40:41 +00:00
tenraku ou
c1cad3d7a9 Renamed get-value.ts to value-getter.ts 2024-06-03 07:40:09 +00:00
tenraku ou
c378bfe20c Deleted quasar-project 2024-06-03 07:26:53 +00:00
Yukina Mori
0e0d028c24 Merged PR 26: 修正版 feat: #234 フィールドに値を挿入するコンポーネントの追加
feat: #234 フィールドに値を挿入するコンポーネントの追加

フィールドに値を挿入するコンポーネントの新規追加です。

Related work items: #234
2024-06-03 04:57:23 +00:00
Moriyukina2
3b6eed32ec feat: #234 フィールドに値を挿入するコンポーネントの追加
フィールドに値を挿入するコンポーネントの新規追加です。
2024-06-03 13:45:41 +09:00
Takuto Yoshida(タクト)
f62a7c3389 Merged PR 24: feat:現在時刻の取得
feat:現在時刻の取得

Related work items: #237
2024-06-03 03:35:41 +00:00
takuto
a161d8e2c8 feat:現在時刻の取得 2024-06-03 03:35:14 +09:00
wtl
b97888fca9 文字数チェック属性名変更 2024-05-30 15:28:55 +09:00
wtl
371ec3a133 メールチェックインターフェース更新 2024-05-30 15:14:54 +09:00
tenraku ou
711b9afaea Merged PR 23: メールアドレスチェック 文字数チェック 正規表現チェック追加
1.メールアドレスチェック email-check addin
2.文字数チェック counter-check addin
3.正規表現チェック追加 regular-check addin

Related work items: #247, #248, #250
2024-05-30 04:55:09 +00:00
wtl
00227ca713 update console delete 2024-05-29 10:14:52 +09:00
wtl
842edd6f1f update console.log delete 2024-05-29 10:05:47 +09:00
wtl
cd0c3197fa add get-value 2024-05-29 09:53:38 +09:00
wtl
7f35a91765 scriptsファイル削除環境変更 2024-05-28 10:20:22 +09:00
c44b42f498 不要ファイル削除 2024-05-28 09:44:36 +09:00
cff6ee5478 feat:メールアドレスチェック 2024-05-27 21:49:52 +09:00
wtl
40b21604f9 環境変更 2024-05-27 18:04:47 +09:00
wtl
98fcd2eb47 文字数チェック追加 2024-05-27 17:24:03 +09:00
Mouriya
c3b560dbc9 条件付きコンポーネントは'source'でappidを受け取ることができる。 2024-05-25 04:15:09 +09:00
53aadfcaaa feat:データ集計処理作成 2024-05-24 09:20:19 +09:00
Mouriya
7fb3d08ccb 細部の問題の修正 2024-05-20 03:38:27 +09:00
Mouriya
cf4209333d データ処理書き込み完了 2024-05-17 23:32:14 +09:00
Mouriya
61ac281134 verNameのラッピング・オブジェクト 2024-05-17 14:41:15 +09:00
kanarutsuda
22e9094d4c feat全角チェックのソースマージ 2024-05-15 16:19:47 +09:00
kanarutsuda
a13721f63e feat:全角チェックアクション追加 2024-05-15 16:06:42 +09:00
kanarutsuda
05b9a0ce1b feat:全角入力チェックアクション追加 2024-05-15 12:14:28 +09:00
Mouriya
b25c17ab53 cssとjsを1つのファイルにまとめるためのviteプラグインを追加。 2024-05-13 16:11:52 +09:00
Mouriya
64d2cadd82 2つのデータ計算コンポーネントを追加する 2024-05-13 06:56:44 +09:00
Mouriya
371e2ee073 add vueuse dependencies 2024-05-13 06:56:03 +09:00
Mouriya
a7078b54c5 イベントに削除関数を追加し、即座に適用する 2024-05-13 01:16:09 +09:00
64 changed files with 2781 additions and 1302 deletions

View File

@@ -1,502 +0,0 @@
<#
.Synopsis
Activate a Python virtual environment for the current PowerShell session.
.Description
Pushes the python executable for a virtual environment to the front of the
$Env:PATH environment variable and sets the prompt to signify that you are
in a Python virtual environment. Makes use of the command line switches as
well as the `pyvenv.cfg` file values present in the virtual environment.
.Parameter VenvDir
Path to the directory that contains the virtual environment to activate. The
default value for this is the parent of the directory that the Activate.ps1
script is located within.
.Parameter Prompt
The prompt prefix to display when this virtual environment is activated. By
default, this prompt is the name of the virtual environment folder (VenvDir)
surrounded by parentheses and followed by a single space (ie. '(.venv) ').
.Example
Activate.ps1
Activates the Python virtual environment that contains the Activate.ps1 script.
.Example
Activate.ps1 -Verbose
Activates the Python virtual environment that contains the Activate.ps1 script,
and shows extra information about the activation as it executes.
.Example
Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
Activates the Python virtual environment located in the specified location.
.Example
Activate.ps1 -Prompt "MyPython"
Activates the Python virtual environment that contains the Activate.ps1 script,
and prefixes the current prompt with the specified string (surrounded in
parentheses) while the virtual environment is active.
.Notes
On Windows, it may be required to enable this Activate.ps1 script by setting the
execution policy for the user. You can do this by issuing the following PowerShell
command:
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
For more information on Execution Policies:
https://go.microsoft.com/fwlink/?LinkID=135170
#>
Param(
[Parameter(Mandatory = $false)]
[String]
$VenvDir,
[Parameter(Mandatory = $false)]
[String]
$Prompt
)
<# Function declarations --------------------------------------------------- #>
<#
.Synopsis
Remove all shell session elements added by the Activate script, including the
addition of the virtual environment's Python executable from the beginning of
the PATH variable.
.Parameter NonDestructive
If present, do not remove this function from the global namespace for the
session.
#>
function global:deactivate ([switch]$NonDestructive) {
# Revert to original values
# The prior prompt:
if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
}
# The prior PYTHONHOME:
if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
}
# The prior PATH:
if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
Remove-Item -Path Env:_OLD_VIRTUAL_PATH
}
# Just remove the VIRTUAL_ENV altogether:
if (Test-Path -Path Env:VIRTUAL_ENV) {
Remove-Item -Path env:VIRTUAL_ENV
}
# Just remove VIRTUAL_ENV_PROMPT altogether.
if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
Remove-Item -Path env:VIRTUAL_ENV_PROMPT
}
# Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
}
# Leave deactivate function in the global namespace if requested:
if (-not $NonDestructive) {
Remove-Item -Path function:deactivate
}
}
<#
.Description
Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
given folder, and returns them in a map.
For each line in the pyvenv.cfg file, if that line can be parsed into exactly
two strings separated by `=` (with any amount of whitespace surrounding the =)
then it is considered a `key = value` line. The left hand string is the key,
the right hand is the value.
If the value starts with a `'` or a `"` then the first and last character is
stripped from the value before being captured.
.Parameter ConfigDir
Path to the directory that contains the `pyvenv.cfg` file.
#>
function Get-PyVenvConfig(
[String]
$ConfigDir
) {
Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
# Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
$pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
# An empty map will be returned if no config file is found.
$pyvenvConfig = @{ }
if ($pyvenvConfigPath) {
Write-Verbose "File exists, parse `key = value` lines"
$pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
$pyvenvConfigContent | ForEach-Object {
$keyval = $PSItem -split "\s*=\s*", 2
if ($keyval[0] -and $keyval[1]) {
$val = $keyval[1]
# Remove extraneous quotations around a string value.
if ("'""".Contains($val.Substring(0, 1))) {
$val = $val.Substring(1, $val.Length - 2)
}
$pyvenvConfig[$keyval[0]] = $val
Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
}
}
}
return $pyvenvConfig
}
<# Begin Activate script --------------------------------------------------- #>
# Determine the containing directory of this script
$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$VenvExecDir = Get-Item -Path $VenvExecPath
Write-Verbose "Activation script is located in path: '$VenvExecPath'"
Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
# Set values required in priority: CmdLine, ConfigFile, Default
# First, get the location of the virtual environment, it might not be
# VenvExecDir if specified on the command line.
if ($VenvDir) {
Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
}
else {
Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
$VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
Write-Verbose "VenvDir=$VenvDir"
}
# Next, read the `pyvenv.cfg` file to determine any required value such
# as `prompt`.
$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
# Next, set the prompt from the command line, or the config file, or
# just use the name of the virtual environment folder.
if ($Prompt) {
Write-Verbose "Prompt specified as argument, using '$Prompt'"
}
else {
Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
$Prompt = $pyvenvCfg['prompt'];
}
else {
Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
$Prompt = Split-Path -Path $venvDir -Leaf
}
}
Write-Verbose "Prompt = '$Prompt'"
Write-Verbose "VenvDir='$VenvDir'"
# Deactivate any currently active virtual environment, but leave the
# deactivate function in place.
deactivate -nondestructive
# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
# that there is an activated venv.
$env:VIRTUAL_ENV = $VenvDir
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
Write-Verbose "Setting prompt to '$Prompt'"
# Set the prompt to include the env name
# Make sure _OLD_VIRTUAL_PROMPT is global
function global:_OLD_VIRTUAL_PROMPT { "" }
Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
function global:prompt {
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
_OLD_VIRTUAL_PROMPT
}
$env:VIRTUAL_ENV_PROMPT = $Prompt
}
# Clear PYTHONHOME
if (Test-Path -Path Env:PYTHONHOME) {
Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
Remove-Item -Path Env:PYTHONHOME
}
# Add the venv to the PATH
Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
# SIG # Begin signature block
# MIIvIgYJKoZIhvcNAQcCoIIvEzCCLw8CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBnL745ElCYk8vk
# dBtMuQhLeWJ3ZGfzKW4DHCYzAn+QB6CCE8MwggWQMIIDeKADAgECAhAFmxtXno4h
# MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z
# ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
# IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
# AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z
# G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ
# anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s
# Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL
# 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb
# BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3
# JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c
# AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx
# YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0
# viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL
# T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud
# EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf
# Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk
# aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS
# PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK
# 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB
# cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp
# 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg
# dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri
# RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7
# 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5
# nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3
# i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H
# EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G
# CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
# IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
# ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C
# 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce
# 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da
# E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T
# SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA
# FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh
# D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM
# 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z
# 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05
# huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY
# mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP
# /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T
# AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD
# VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG
# A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY
# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj
# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV
# HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
# cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN
# BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry
# sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL
# IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf
# Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh
# OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh
# dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV
# 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j
# wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH
# Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC
# XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l
# /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW
# eE4wggd3MIIFX6ADAgECAhAHHxQbizANJfMU6yMM0NHdMA0GCSqGSIb3DQEBCwUA
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
# ODQgMjAyMSBDQTEwHhcNMjIwMTE3MDAwMDAwWhcNMjUwMTE1MjM1OTU5WjB8MQsw
# CQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQHEwlCZWF2ZXJ0b24x
# IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMSMwIQYDVQQDExpQ
# eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
# ADCCAgoCggIBAKgc0BTT+iKbtK6f2mr9pNMUTcAJxKdsuOiSYgDFfwhjQy89koM7
# uP+QV/gwx8MzEt3c9tLJvDccVWQ8H7mVsk/K+X+IufBLCgUi0GGAZUegEAeRlSXx
# xhYScr818ma8EvGIZdiSOhqjYc4KnfgfIS4RLtZSrDFG2tN16yS8skFa3IHyvWdb
# D9PvZ4iYNAS4pjYDRjT/9uzPZ4Pan+53xZIcDgjiTwOh8VGuppxcia6a7xCyKoOA
# GjvCyQsj5223v1/Ig7Dp9mGI+nh1E3IwmyTIIuVHyK6Lqu352diDY+iCMpk9Zanm
# SjmB+GMVs+H/gOiofjjtf6oz0ki3rb7sQ8fTnonIL9dyGTJ0ZFYKeb6BLA66d2GA
# LwxZhLe5WH4Np9HcyXHACkppsE6ynYjTOd7+jN1PRJahN1oERzTzEiV6nCO1M3U1
# HbPTGyq52IMFSBM2/07WTJSbOeXjvYR7aUxK9/ZkJiacl2iZI7IWe7JKhHohqKuc
# eQNyOzxTakLcRkzynvIrk33R9YVqtB4L6wtFxhUjvDnQg16xot2KVPdfyPAWd81w
# tZADmrUtsZ9qG79x1hBdyOl4vUtVPECuyhCxaw+faVjumapPUnwo8ygflJJ74J+B
# Yxf6UuD7m8yzsfXWkdv52DjL74TxzuFTLHPyARWCSCAbzn3ZIly+qIqDAgMBAAGj
# ggIGMIICAjAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNVHQ4E
# FgQUt/1Teh2XDuUj2WW3siYWJgkZHA8wDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM
# MAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwzLmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNI
# QTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5jb20v
# RGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0Ex
# LmNybDA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUFBwIBFhtodHRwOi8v
# d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgZQGCCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUF
# BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6
# Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu
# aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZI
# hvcNAQELBQADggIBABxv4AeV/5ltkELHSC63fXAFYS5tadcWTiNc2rskrNLrfH1N
# s0vgSZFoQxYBFKI159E8oQQ1SKbTEubZ/B9kmHPhprHya08+VVzxC88pOEvz68nA
# 82oEM09584aILqYmj8Pj7h/kmZNzuEL7WiwFa/U1hX+XiWfLIJQsAHBla0i7QRF2
# de8/VSF0XXFa2kBQ6aiTsiLyKPNbaNtbcucaUdn6vVUS5izWOXM95BSkFSKdE45O
# q3FForNJXjBvSCpwcP36WklaHL+aHu1upIhCTUkzTHMh8b86WmjRUqbrnvdyR2yd
# I5l1OqcMBjkpPpIV6wcc+KY/RH2xvVuuoHjlUjwq2bHiNoX+W1scCpnA8YTs2d50
# jDHUgwUo+ciwpffH0Riq132NFmrH3r67VaN3TuBxjI8SIZM58WEDkbeoriDk3hxU
# 8ZWV7b8AW6oyVBGfM06UgkfMb58h+tJPrFx8VI/WLq1dTqMfZOm5cuclMnUHs2uq
# rRNtnV8UfidPBL4ZHkTcClQbCoz0UbLhkiDvIS00Dn+BBcxw/TKqVL4Oaz3bkMSs
# M46LciTeucHY9ExRVt3zy7i149sd+F4QozPqn7FrSVHXmem3r7bjyHTxOgqxRCVa
# 18Vtx7P/8bYSBeS+WHCKcliFCecspusCDSlnRUjZwyPdP0VHxaZg2unjHY3rMYIa
# tTCCGrECAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIElu
# Yy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJT
# QTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAHHxQbizANJfMU6yMM0NHdMA0GCWCGSAFl
# AwQCAQUAoIHIMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC
# AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCBnAZ6P7YvTwq0fbF62
# o7E75R0LxsW5OtyYiFESQckLhjBcBgorBgEEAYI3AgEMMU4wTKBGgEQAQgB1AGkA
# bAB0ADoAIABSAGUAbABlAGEAcwBlAF8AdgAzAC4AMQAxAC4ANABfADIAMAAyADMA
# MAA2ADAANwAuADAAMaECgAAwDQYJKoZIhvcNAQEBBQAEggIAVdxtEr9NH8SoVTzT
# o/jdr3t1yqExSecge3YGCu9USfMqLtmCKzG5r2rf3xZkJ6CpvmHwji3FUY6Hl991
# Ttd0eEEpjeEse9gotnojgHTQACJntGuPcK+65jIQYNvp3JIuczjTW0JjWkJf4lqI
# hVS6rEc00D/0NsUF9BbNkjNZ0AUQeOWe2WZJnqRRFN4U3pToN51NDjpEtRjlNTkc
# SzoNO7ZyEsSXkNenlgbgS1yXEQ8v4bbnbPyyL+2yWMG1QsLv6M3OV0kXx9aow1r5
# gZ1mCjBkbtWKH58WVBoepUaPYTjFBWCT2pDrorbg6cguwBdyz7s8X+WlCD4ycFfW
# o95x7u1W9RwPPPppszr8Pd4jZSbEXEQ/G9Ke5NvTvNmK93b7/kySfNYfwW2meP6E
# JIc0R9DMSZlK+ChtU5mmvo4e6YQTLXIXQhPIz7jVNlUjXMJX7WALjE72EDdC5MpQ
# ygW7wue6EhjlUVXT4pEIySCGaXxUzRi1oh+Q+Jbe3rDvhSPZUWzCqEtOkJ35dLYh
# D9Rahi2BM1qaepfu1wVtSXbVbc0SDPjloojEmTyDnk61u5epo0E0oHqNAU8t1ZTN
# +Guptl/agMp52uRsaC5Bi276icqRtclfx9E4SfJEiw7xRlImCclMpw2dRsyzIrpb
# MKpWDAno4rClgYS3M9lqQ71RlXehghc+MIIXOgYKKwYBBAGCNwMDATGCFyowghcm
# BgkqhkiG9w0BBwKgghcXMIIXEwIBAzEPMA0GCWCGSAFlAwQCAQUAMHgGCyqGSIb3
# DQEJEAEEoGkEZzBlAgEBBglghkgBhv1sBwEwMTANBglghkgBZQMEAgEFAAQgsPGH
# UIiYgGXi/94WNZrP+V1kV/B5SVJn3ck+XzTJ0aACEQCJ79BpOkCDCW06IgZOU3EQ
# GA8yMDIzMDYwNzA1NTc0NFqgghMHMIIGwDCCBKigAwIBAgIQDE1pckuU+jwqSj0p
# B4A9WjANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln
# aUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5
# NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTIyMDkyMTAwMDAwMFoXDTMzMTEy
# MTIzNTk1OVowRjELMAkGA1UEBhMCVVMxETAPBgNVBAoTCERpZ2lDZXJ0MSQwIgYD
# VQQDExtEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMiAtIDIwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQDP7KUmOsap8mu7jcENmtuh6BSFdDMaJqzQHFUeHjZt
# vJJVDGH0nQl3PRWWCC9rZKT9BoMW15GSOBwxApb7crGXOlWvM+xhiummKNuQY1y9
# iVPgOi2Mh0KuJqTku3h4uXoW4VbGwLpkU7sqFudQSLuIaQyIxvG+4C99O7HKU41A
# gx7ny3JJKB5MgB6FVueF7fJhvKo6B332q27lZt3iXPUv7Y3UTZWEaOOAy2p50dIQ
# kUYp6z4m8rSMzUy5Zsi7qlA4DeWMlF0ZWr/1e0BubxaompyVR4aFeT4MXmaMGgok
# vpyq0py2909ueMQoP6McD1AGN7oI2TWmtR7aeFgdOej4TJEQln5N4d3CraV++C0b
# H+wrRhijGfY59/XBT3EuiQMRoku7mL/6T+R7Nu8GRORV/zbq5Xwx5/PCUsTmFnta
# fqUlc9vAapkhLWPlWfVNL5AfJ7fSqxTlOGaHUQhr+1NDOdBk+lbP4PQK5hRtZHi7
# mP2Uw3Mh8y/CLiDXgazT8QfU4b3ZXUtuMZQpi+ZBpGWUwFjl5S4pkKa3YWT62SBs
# GFFguqaBDwklU/G/O+mrBw5qBzliGcnWhX8T2Y15z2LF7OF7ucxnEweawXjtxojI
# sG4yeccLWYONxu71LHx7jstkifGxxLjnU15fVdJ9GSlZA076XepFcxyEftfO4tQ6
# dwIDAQABo4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYD
# VR0lAQH/BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZI
# AYb9bAcBMB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQW
# BBRiit7QYfyPMRTtlwvNPSqUFN9SnDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8v
# Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2
# VGltZVN0YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcw
# AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8v
# Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hB
# MjU2VGltZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQBVqioa80bz
# eFc3MPx140/WhSPx/PmVOZsl5vdyipjDd9Rk/BX7NsJJUSx4iGNVCUY5APxp1Mqb
# KfujP8DJAJsTHbCYidx48s18hc1Tna9i4mFmoxQqRYdKmEIrUPwbtZ4IMAn65C3X
# CYl5+QnmiM59G7hqopvBU2AJ6KO4ndetHxy47JhB8PYOgPvk/9+dEKfrALpfSo8a
# OlK06r8JSRU1NlmaD1TSsht/fl4JrXZUinRtytIFZyt26/+YsiaVOBmIRBTlClmi
# a+ciPkQh0j8cwJvtfEiy2JIMkU88ZpSvXQJT657inuTTH4YBZJwAwuladHUNPeF5
# iL8cAZfJGSOA1zZaX5YWsWMMxkZAO85dNdRZPkOaGK7DycvD+5sTX2q1x+DzBcNZ
# 3ydiK95ByVO5/zQQZ/YmMph7/lxClIGUgp2sCovGSxVK05iQRWAzgOAj3vgDpPZF
# R+XOuANCR+hBNnF3rf2i6Jd0Ti7aHh2MWsgemtXC8MYiqE+bvdgcmlHEL5r2X6cn
# l7qWLoVXwGDneFZ/au/ClZpLEQLIgpzJGgV8unG1TnqZbPTontRamMifv427GFxD
# 9dAq6OJi7ngE273R+1sKqHB+8JeEeOMIA11HLGOoJTiXAdI/Otrl5fbmm9x+LMz/
# F0xNAKLY1gEOuIvu5uByVYksJxlh9ncBjDCCBq4wggSWoAMCAQICEAc2N7ckVHzY
# R6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoT
# DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UE
# AxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3
# MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
# bmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2
# IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
# AMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjz
# aPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3E
# F3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYnc
# fGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8O
# pWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROp
# VymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4i
# FNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmif
# tkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0
# UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9Ne
# S3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCj
# WAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTAS
# BgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57I
# bzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMC
# AYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUF
# BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6
# Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0
# MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp
# Q2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCG
# SAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAY
# LhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQx
# Z822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf
# 7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDV
# inF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7
# +6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJ
# D5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvk
# OHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJG
# nXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimG
# sJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38A
# C+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d
# 2zc4GqEr9u3WfPwwggWNMIIEdaADAgECAhAOmxiO+dAt5+/bUOIIQBhaMA0GCSqG
# SIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFz
# c3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBaFw0zMTExMDkyMzU5NTla
# MGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT
# EHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9v
# dCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8
# MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauy
# efLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34Lz
# B4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+x
# embud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhA
# kHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1Lyu
# GwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2
# PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37A
# lLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD7
# 6GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/
# ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXA
# j6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIBNjAPBgNVHRMBAf8EBTAD
# AQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF
# 66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMCAYYweQYIKwYBBQUHAQEE
# bTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYB
# BQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy
# ZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDARBgNVHSAECjAI
# MAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0NcVec4X6CjdBs9thbX979X
# B72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnovLbc47/T/gLn4offyct4k
# vFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65ZyoUi0mcudT6cGAxN3J0TU
# 53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFWjuyk1T3osdz9HNj0d1pc
# VIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPFmCLBsln1VWvPJ6tsds5v
# Iy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9ztwGpn1eqXijiuZQxggN2
# MIIDcgIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5j
# LjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBU
# aW1lU3RhbXBpbmcgQ0ECEAxNaXJLlPo8Kko9KQeAPVowDQYJYIZIAWUDBAIBBQCg
# gdEwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0y
# MzA2MDcwNTU3NDRaMCsGCyqGSIb3DQEJEAIMMRwwGjAYMBYEFPOHIk2GM4KSNamU
# vL2Plun+HHxzMC8GCSqGSIb3DQEJBDEiBCAZCWWaBjTHAZnsndSxyxCaZSOrTyqo
# O35hv3VOlS9KHDA3BgsqhkiG9w0BCRACLzEoMCYwJDAiBCDH9OG+MiiJIKviJjq+
# GsT8T+Z4HC1k0EyAdVegI7W2+jANBgkqhkiG9w0BAQEFAASCAgBt92vHxbHXh4Z2
# yl+aTo7PltgPhZhoQCWg+gDSyySEqkDN+kTuoW3ROuMjR1JR0htJOwVqnmI/enhW
# r8VJiDKfGOGupHEfzAlMaIIC+K+C3sSoeaRR1aiOWrUA/oPpJIgwXyfo65Hf07qf
# wdn//4y5zv6oMdHNtpSfFgibze5BjNRAgOUxl9rvKArEN7B+WTCnvLWw/EJe48MQ
# B0zUbVFIORQUHlLnCL07JGRSN5bHaMtnn5eEwZFC9522kJaHyLrmfeP4jZLMhjhn
# fGxv69HVzggM8CpjpQA8l8hh6Il48TDMZpdqkxwjoRmJVwt3hwTrfuE11NFrXEAD
# 8dAAta6N/M722c3BE6UxM2R4QXyV05BL6e4jVJm1aR1ebUVS4nZVZ/jbCexR/+vx
# mfSh1SezU3KlgRMDrLF+El883BFoe/99p4/QjjnELhn41lPPAYGefhMI9ioYZULQ
# xMyG6qIPA8s2tnYIL/AKvh7SUgFVtOsTKbTFXMMr20sipBQQFUOb8ZD+8u4Iyc4M
# UC4d2S6z9zwlPbSr1lk9m3R8rl+j2/VkB1S21nqda3xWFk/+n/2oEJe4gUkCiQxs
# qFaykkcAhWYdZVRRNM89ZF23DeYAEkUEaD2M1ld0CZNtvtPNmv/NZV/Xbb3H0RPR
# yDBB2JQI1BbEjl7HWy616MUsAqWA+Q==
# SIG # End signature block

View File

@@ -1,69 +0,0 @@
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () {
# reset old environment variables
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
PATH="${_OLD_VIRTUAL_PATH:-}"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r 2> /dev/null
fi
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
PS1="${_OLD_VIRTUAL_PS1:-}"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
unset VIRTUAL_ENV_PROMPT
if [ ! "${1:-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="C:\project\Kintone\KintoneAppBuilder\backend"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/Scripts:$PATH"
export PATH
# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
PS1="(backend) ${PS1:-}"
export PS1
VIRTUAL_ENV_PROMPT="(backend) "
export VIRTUAL_ENV_PROMPT
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r 2> /dev/null
fi

View File

@@ -1,34 +0,0 @@
@echo off
rem This file is UTF-8 encoded, so we need to update the current code page while executing it
for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do (
set _OLD_CODEPAGE=%%a
)
if defined _OLD_CODEPAGE (
"%SystemRoot%\System32\chcp.com" 65001 > nul
)
set VIRTUAL_ENV=C:\project\Kintone\KintoneAppBuilder\backend
if not defined PROMPT set PROMPT=$P$G
if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT%
if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%
set _OLD_VIRTUAL_PROMPT=%PROMPT%
set PROMPT=(backend) %PROMPT%
if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%
set PYTHONHOME=
if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%
set PATH=%VIRTUAL_ENV%\Scripts;%PATH%
set VIRTUAL_ENV_PROMPT=(backend)
:END
if defined _OLD_CODEPAGE (
"%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul
set _OLD_CODEPAGE=
)

View File

@@ -1,22 +0,0 @@
@echo off
if defined _OLD_VIRTUAL_PROMPT (
set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
)
set _OLD_VIRTUAL_PROMPT=
if defined _OLD_VIRTUAL_PYTHONHOME (
set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%"
set _OLD_VIRTUAL_PYTHONHOME=
)
if defined _OLD_VIRTUAL_PATH (
set "PATH=%_OLD_VIRTUAL_PATH%"
)
set _OLD_VIRTUAL_PATH=
set VIRTUAL_ENV=
set VIRTUAL_ENV_PROMPT=
:END

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -217,7 +217,9 @@ def deoployappfromkintone(app:str,revision:str,c:config.KINTONE_ENV):
data = {"apps":[{"app":app,"revision":revision}],"revert": False}
r = httpx.post(url,headers=headers,data=json.dumps(data))
return r.json
# 既定項目に含めるアプリのフィールドのみ取得する
# スペース、枠線、ラベルを含まない
def getfieldsfromkintone(app:str,c:config.KINTONE_ENV):
headers={config.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE}
params = {"app":app}
@@ -225,6 +227,44 @@ def getfieldsfromkintone(app:str,c:config.KINTONE_ENV):
r = httpx.get(url,headers=headers,params=params)
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):
updatefields={}
addfields={}
@@ -482,6 +522,15 @@ async def appfields(request:Request,app:str,env = Depends(getkintoneenv)):
except Exception as 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")
async def appprocess(request:Request,app:str,env = Depends(getkintoneenv)):
try:

View File

@@ -328,7 +328,7 @@ async def event_data(
@r.get(
"/eventactions/{eventid}",
"/eventactions",
response_model=t.List[Action],
response_model_exclude={"id"},
response_model_exclude_none=True,

View File

@@ -12,15 +12,15 @@ API_V1_AUTH_KEY = "X-Cybozu-Authorization"
DEPLOY_MODE = "DEV" #DEV,PROD
#DEPLOY_JS_URL = "https://ka-addin.azurewebsites.net/alc_runtime.js"
DEPLOY_JS_URL = "https://92dc-133-139-109-57.ngrok-free.app/alc_runtime.js"
DEPLOY_JS_URL = "https://ka-addin.azurewebsites.net/alc_runtime.js"
#DEPLOY_JS_URL = "https://ce1c-133-139-70-194.ngrok-free.app/alc_runtime.js"
KINTONE_FIELD_TYPE=["GROUP","GROUP_SELECT","CHECK_BOX","SUBTABLE","DROP_DOWN","USER_SELECT","RADIO_BUTTON","RICH_TEXT","LINK","REFERENCE_TABLE","CALC","TIME","NUMBER","ORGANIZATION_SELECT","FILE","DATETIME","DATE","MULTI_SELECT","SINGLE_LINE_TEXT","MULTI_LINE_TEXT"]
KINTONE_FIELD_PROPERTY=['label','code','type','required','unique','maxValue','minValue','maxLength','minLength','defaultValue','defaultNowValue','options','expression','hideExpression','digit','protocol','displayScale','unit','unitPosition']
class KINTONE_ENV:
BASE_URL = ""
API_V1_AUTH_VALUE = ""

View File

@@ -280,7 +280,8 @@ def get_events(db: Session):
def get_eventactions(db: Session,eventid: str):
#eveactions = db.query(models.Action).join(models.EventAction,models.EventAction.actionid == models.Action.id ).join(models.Event,models.Event.id == models.EventAction.eventid).filter(models.Event.eventid == eventid).all()
eveactions = db.query(models.Action).join(models.EventAction,models.EventAction.actionid != models.Action.id and models.EventAction.eventid == eventid ).join(models.Event,models.Event.id == models.EventAction.eventid).filter(models.Event.eventid == eventid).all()
blackactions = db.query(models.Action.id).join(models.EventAction,and_(models.EventAction.actionid == models.Action.id,models.EventAction.eventid == eventid)).subquery()
eveactions = db.query(models.Action).filter(models.Action.id.notin_(blackactions)).order_by(models.Action.id).all()
if not eveactions:
raise HTTPException(status_code=404, detail="Data not found")
return eveactions

View File

@@ -90,7 +90,7 @@ class Event(Base):
class EventAction(Base):
__tablename__ = "eventaction"
eventid = Column(Integer,ForeignKey("event.id"))
eventid = Column(String(100),ForeignKey("event.eventid"))
actionid = Column(Integer,ForeignKey("action.id"))

View File

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

View File

@@ -1,2 +1,2 @@
# KAB_BACKEND_URL="https://kab-backend.azurewebsites.net/"
KAB_BACKEND_URL="http://127.0.0.1:8000/"
KAB_BACKEND_URL="https://kab-backend.azurewebsites.net/"
#KAB_BACKEND_URL="http://127.0.0.1:8000/"

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
<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>
<q-btn flat round dense icon="more_vert" >
<q-menu auto-close anchor="bottom start">

View File

@@ -6,21 +6,21 @@
{{ selectedObject.name }}
</q-chip>
<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>
</template>
<template v-slot:append>
<q-icon name="search" class="cursor-pointer" @click="showDg"/>
</template>
</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>
<q-input dense debounce="200" v-model="filter" placeholder="検索" clearable>
<template v-slot:before>
<q-icon name="search" />
</template>
</q-input>
</template>
</template>
<condition-objects ref="appDg" name="フィールド" type="single" :filter="filter" :appId="store.appInfo?.appId" :vars="vars"></condition-objects>
</show-dialog>
</template>
@@ -88,9 +88,9 @@
.condition-object{
min-width: 200px;
max-height: 40px;
padding: 2px;
margin: 0 2px;
}
.selected-obj{
margin: 0px;
margin: 0 2px;
}
</style>

View File

@@ -66,7 +66,7 @@
</div>
<!-- condition -->
<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>
<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)"
@@ -257,12 +257,12 @@ export default defineComponent( {
.condition-value{
min-width: 200px;
max-height: 40px;
padding: 2px;
margin: 0 2px;
}
.operator{
min-width: 150px;
max-height: 40px;
padding: 2px;
margin: 0 2px;
text-align: center;
font-size: 12pt;
}

View File

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

View File

@@ -1,51 +1,51 @@
<template>
<div class="q-pa-md">
<q-table flat bordered :loading="!isLoaded" row-key="name" :selection="type"
:selected="modelValue"
@update:selected="$emit('update:modelValue', $event)"
:filter="filter"
:columns="columns" :rows="rows" />
<q-table flat bordered :loading="!isLoaded" row-key="name" :selection="type" :selected="modelValue"
@update:selected="$emit('update:modelValue', $event)" :filter="filter" :columns="columns" :rows="rows" />
</div>
</template>
<script>
import { ref, onMounted, reactive } from 'vue'
<script lang="ts">
import { useAsyncState } from '@vueuse/core';
import { api } from 'boot/axios';
import { computed } from 'vue';
export default {
name: 'FieldList',
props: {
fields: Array,
name: String,
type: String,
appId: Number,
modelValue:Array,
filter:String
},
emits:[
'update:modelValue'
],
modelValue: Array,
filter: String
},
emits: [
'update:modelValue'
],
setup(props) {
const isLoaded = ref(false);
// const rows = ref([]);
// const isLoaded = ref(false);
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: '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 {
columns,
rows,

View File

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

View File

@@ -1,7 +1,7 @@
<template>
<!-- <div class="q-pa-md q-gutter-sm" > -->
<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-title>{{ name }}</q-toolbar-title>
<q-space></q-space>

View File

@@ -1,43 +1,59 @@
<template>
<div class="q-pa-md">
<q-table flat bordered row-key="name" :selection="type"
:selected="modelValue"
@update:selected="$emit('update:modelValue', $event)"
:columns="columns" :rows="rows" />
<q-table flat bordered row-key="id" :selection="type" :selected="modelValue"
@update:selected="$emit('update:modelValue', $event)" :columns="columns" :rows="rows" />
</div>
</template>
<script lang="ts">
import { ref, reactive, PropType, compile } from 'vue';
import {IActionNode,IActionVariable} from '../types/ActionTypes';
import { PropType, reactive } from 'vue';
import { IActionVariable } from '../types/ActionTypes';
import { v4 as uuidv4 } from 'uuid';
export default {
name: 'VariableList',
props: {
name: String,
type: String,
vars:{
type:Array as PropType<IActionVariable[]>,
reqired:true,
default:()=>[]
vars: {
type: Array as PropType<IActionVariable[]>,
reqired: true,
default: () => []
},
modelValue:Array
modelValue: Array
},
emits:[
'update:modelValue'
],
emits: [
'update:modelValue'
],
setup(props) {
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: 'name',required: true, sortable: true }
const variableName = (field) => {
const name = field.name;
return name.name;
}
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 {
columns,
rows:reactive(rows)
rows: reactive(rows)
}
}
}

View File

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

View File

@@ -205,7 +205,7 @@ export default defineComponent({
*/
const varName =(node:IActionNode)=>{
const prop = node.actionProps.find((prop) => prop.props.name === "verName");
return prop?.props.modelValue;
return prop?.props.modelValue.name;
};
const copyFlow=()=>{
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-item :key="index" dense clickable >
<q-item-section>
<q-item-label>
{{ item.label }}
</q-item-label>
<q-item-label>
{{ item.label }}
</q-item-label>
</q-item-section>
<q-item-section side>
<q-btn round flat size="sm" icon="clear" @click="removeField(index)" />
@@ -81,8 +81,8 @@
</div>
</div>
<div class="row">
<field-select ref="fieldDlg" name="フィールド" :type="selectType" :updateSelects="updateItems"
:appId="selectedField.app?.id" not_page :filter="fieldFilter" :selectedFields="selectedField.fields"></field-select>
<field-select ref="fieldDlg" name="フィールド" :type="selectType"
:appId="selectedField.app?.id" not_page :filter="fieldFilter" :selectedFields="selectedField.fields" :fieldTypes="fieldTypes"></field-select>
</div>
</div>
</div>
@@ -99,9 +99,7 @@
</template>
</q-input>
</template>
<AppSelect ref="appDlg" name="アプリ" type="single" :filter="filter"
:updateExternalSelectAppInfo="updateExternalSelectAppInfo"></AppSelect>
<AppSelect ref="appDlg" name="アプリ" type="single" :filter="filter" ></AppSelect>
</show-dialog>
</template>
@@ -128,7 +126,7 @@ interface IAppFields{
export default defineComponent({
inheritAttrs:false,
name: 'FieldInput',
name: 'AppFieldSelect',
components: {
ShowDialog,
FieldSelect,
@@ -154,6 +152,10 @@ export default defineComponent({
selectType:{
type:String,
default:'single'
},
fieldTypes:{
type:Array,
default:()=>[]
}
},
setup(props, { emit }) {
@@ -197,13 +199,6 @@ export default defineComponent({
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)=>{
selectedField.value.fields.splice(index,1);
@@ -223,9 +218,7 @@ export default defineComponent({
selectedField,
showSelectApp,
isSelected,
updateExternalSelectAppInfo,
filter: ref(),
updateItems,
clear,
fieldFilter: ref(),
removeField

View File

@@ -1,12 +1,12 @@
<template>
<div v-bind="$attrs">
<q-field v-model="tree" :label="displayName" labelColor="primary" stack-label >
<template v-slot:control >
<q-field v-model="tree" :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="showDg()">クリックで設定{{ isSetted?'設定済み':'未設定' }}</q-btn>
<q-btn color="grey-3" text-color="black" @click="showDg()">クリックで設定{{ isSetted ? '設定済み' : '未設定' }}</q-btn>
</q-card-actions>
<q-card-section class="text-caption" >
<q-card-section class="text-caption">
<div v-if="!isSetted">{{ placeholder }}</div>
<div v-else>{{ conditionString }}</div>
</q-card-section>
@@ -17,82 +17,118 @@
</div>
</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(()=>{
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
};
type Props = {
props?: {
name: string;
modelValue?: {
fields: {
type: string;
label: string;
code: string;
}[]
}
});
</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)){
return;
}
customEvents.events.push(
new kintoneEvent(
displayName,
addEventId,
customButtonId)
);
customEvents.events.push({
eventId: addEventId,
label: displayName,
parentId: customButtonId,
header: 'DELETABLE'
});
}
}

View File

@@ -7,9 +7,6 @@
{{ selectedField.name }}
</q-chip>
</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">
{{ placeholder }}
</template>
@@ -19,7 +16,7 @@
</template>
</q-field>
<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>
</div>
</template>
@@ -54,6 +51,14 @@ export default defineComponent({
type: String,
default: '',
},
selectType:{
type:String,
default:'single'
},
fieldTypes:{
type:Array,
default:()=>[]
},
hint: {
type: String,
default: '',

View File

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

View File

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

View File

@@ -1,11 +1,12 @@
<template>
<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>
</template>
<script lang="ts">
import { defineComponent,ref,watchEffect } from 'vue';
import { defineComponent,ref,watchEffect,computed } from 'vue';
export default defineComponent({
name: 'SelectBox',
@@ -23,20 +24,27 @@ export default defineComponent({
type: Array,
required: true,
},
selectType:{
type:String,
default:'',
},
modelValue: {
type: String,
default: '',
type: [Array,String],
default: null,
},
},
setup(props, { emit }) {
const selectedValue = ref(props.modelValue);
const multiple = computed(()=>{
return props.selectType==='multiple'
});
watchEffect(() => {
emit('update:modelValue', selectedValue.value);
});
return {
selectedValue
selectedValue,
multiple
};
},
});

View File

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

View File

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

View File

@@ -45,7 +45,16 @@ export interface IActionProperty {
export interface IActionVariable{
actionName: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[]{
let varNames:IActionVariable[]=[];
if(prevNode.varName!==undefined && prevNode.varName.modelValue){
if(prevNode.varName.modelValue ==='object'){
console.log(prevNode);
}
varNames.unshift({
actionName:prevNode.name,
displayName:prevNode.varName.displayName,

View File

@@ -198,7 +198,7 @@ export class ConditionTree {
if(value && typeof value ==='object' && ('label' in value)){
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 {
return '';
}

View File

@@ -1,9 +1,10 @@
import {IActionFlow} from './ActionTypes';
import { useFlowEditorStore } from 'src/stores/flowEditor';
import { IActionFlow } from './ActionTypes';
export interface IKintoneEventNode {
label: string;
header:string;
eventId:string;
parentId:string;
header: string;
eventId: string;
parentId: string;
}
export interface IKintoneEvent extends IKintoneEventNode {
@@ -15,60 +16,64 @@ export interface IKintoneEventGroup extends IKintoneEventNode {
events: IKintoneEventNode[];
}
export class kintoneEvent implements IKintoneEvent{
export class kintoneEvent implements IKintoneEvent {
eventId: string;
parentId:string;
get hasFlow(): boolean{
return this.flowData!==undefined && this.flowData.actionNodes.length>1
};
parentId: string;
get hasFlow(): boolean {
return this.flowData !== undefined && this.flowData.actionNodes.length > 1;
}
flowData?: IActionFlow | undefined;
label: string;
get header():string{
return "EVENT";
}
constructor(label:string,eventId:string,parentId:string){
this.eventId=eventId;
this.label=label;
this.parentId=parentId;
header = 'EVENT';
constructor(label: string, eventId: string, parentId: string) {
this.eventId = eventId;
this.label = label;
this.parentId = parentId;
}
}
export class kintoneEventGroup implements IKintoneEventGroup{
export class kintoneEventGroup implements IKintoneEventGroup {
eventId: string;
parentId:string;
parentId: string;
label: string;
events: IKintoneEventNode[];
get header():string{
return "EVENTGROUP";
get header(): string {
return 'EVENTGROUP';
}
constructor(eventId:string,label:string,events:IKintoneEventNode[],parentId:string){
this.eventId=eventId;
this.label=label;
this.events=events;
this.parentId=parentId;
constructor(
eventId: string,
label: string,
events: IKintoneEventNode[],
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;
parentId:string;
parentId: string;
label: string;
events: IKintoneEventNode[];
get header():string{
return "CHANGE";
get header(): string {
return 'CHANGE';
}
constructor(eventId:string,label:string,events:IKintoneEventNode[],parentId:string){
this.eventId=eventId;
this.label=label;
this.events=events;
this.parentId=parentId;
constructor(
eventId: string,
label: string,
events: IKintoneEventNode[],
parentId: string
) {
this.eventId = eventId;
this.label = label;
this.events = events;
this.parentId = parentId;
}
}
export class KintoneEventManager {
public screens: IKintoneEventGroup[];
@@ -76,28 +81,32 @@ export class KintoneEventManager {
this.screens = this.getKintoneEvents();
}
public bindFlows(flows:IActionFlow[]){
this.screens=this.getKintoneEvents();
for (const flow of flows){
const eventId =flow.getRoot()?.name;
if(eventId!==undefined){
public bindFlows(flows: IActionFlow[]) {
this.screens = this.getKintoneEvents();
for (const flow of flows) {
const eventId = flow.getRoot()?.name;
if (eventId !== undefined) {
const eventNode = this.findEventById(eventId);
if(eventNode!==null && eventNode.header==="EVENT"){
const event =eventNode as kintoneEvent;
event.flowData=flow;
}else{
if (eventNode !== null && eventNode.header === 'EVENT') {
const event = eventNode as kintoneEvent;
event.flowData = flow;
} else {
//EventGroupのIDを取得
const lastIndex = eventId.lastIndexOf(".");
const groupId=eventId.substring(0,lastIndex);
const lastIndex = eventId.lastIndexOf('.');
const groupId = eventId.substring(0, lastIndex);
const eventNode = this.findEventById(groupId);
if(eventNode && (eventNode.header==="EVENTGROUP" || eventNode.header==="CHANGE")){
const groupEvent=eventNode as kintoneEventGroup;
const newEvent =new kintoneEvent(
flow.getRoot()?.subTitle || "",
eventId,
groupEvent.parentId
);
newEvent.flowData=flow;
if (eventNode && (eventNode.header === 'EVENTGROUP' || eventNode.header === 'CHANGE')) {
const groupEvent = eventNode as kintoneEventGroup;
const newEvent = {
label: flow.getRoot()?.subTitle || '',
eventId: eventId,
parentId: groupId,
header: 'DELETABLE',
hasFlow: true,
flowData: flow,
};
groupEvent.events.push(newEvent);
}
}
@@ -106,61 +115,193 @@ export class KintoneEventManager {
}
public findEventById(eventId: string): IKintoneEventNode | null {
const screen=this.findScreen(eventId);
if(screen) {return screen;}
const screen = this.findScreen(eventId);
if (screen) {
return screen;
}
for (const screen of this.screens) {
for (const event of screen.events) {
if (event.eventId === eventId) {
return event;
}
if(event.header==="EVENTGROUP"||event.header==="CHANGE"){
const eventGroup = event as IKintoneEventGroup;
const targetEvent = eventGroup.events.find((ev)=>{
return ev.eventId===eventId;
})
if(targetEvent){
return targetEvent;
}
if (event.eventId === eventId) {
return event;
}
if (event.header === 'EVENTGROUP' || event.header === 'CHANGE') {
const eventGroup = event as IKintoneEventGroup;
const targetEvent = eventGroup.events.find((ev) => {
return ev.eventId === eventId;
});
if (targetEvent) {
return targetEvent;
}
}
}
}
return null;
}
public findScreen(eventId:string):IKintoneEventGroup|undefined{
return this.screens.find(screen=>screen.eventId==eventId);
public findScreen(eventId: string): IKintoneEventGroup | undefined {
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 [
new kintoneEventGroup("app.record.create","レコード追加画面",[
new kintoneEvent('レコード追加画面を表示した後','app.record.create.show',"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 kintoneEventGroup('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"),
],"")
new kintoneEventGroup(
'app.record.create',
'レコード追加画面',
[
new kintoneEvent(
'レコード追加画面を表示した',
'app.record.create.show',
'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 kintoneEventGroup(
'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'
),
],
''
),
];
}
}

6
node_modules/.package-lock.json generated vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"name": "App Builder for kintone",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

View File

@@ -6,20 +6,23 @@
"scripts": {
"dev": "tsc && set \"SOURCE_MAP=true\" && vite build && vite preview",
"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",
"preview": "vite preview",
"ngrok":"ngrok http http://localhost:4173/",
"vite":"vite dev"
"ngrok": "ngrok http http://localhost:4173/",
"vite": "vite dev"
},
"devDependencies": {
"@types/jquery": "^3.5.24",
"@types/node": "^20.8.9",
"sass": "^1.69.5",
"typescript": "^5.0.2",
"vite": "^4.4.5"
"vite": "^4.4.5",
"vite-plugin-checker": "^0.6.4"
},
"dependencies": {
"jquery": "^3.7.1",
"vite-plugin-css-injected-by-js": "^3.5.1",
"yarn": "^1.22.22"
}
}

View File

@@ -1,6 +1,6 @@
import { actionAddins } from ".";
import { IField, IAction,IActionResult, IActionNode, IActionProperty, IContext } from "../types/ActionTypes";
import { IField, IAction,IActionResult, IActionNode, IActionProperty, IContext, IVarName } from "../types/ActionTypes";
import { Formatter } from "../util/format";
declare global {
@@ -13,7 +13,7 @@ interface IAutoNumberingProps{
format:string;
prefix:string;
suffix:string;
verName:string;
verName:IVarName;
}
export class AutoNumbering implements IAction{
@@ -29,7 +29,7 @@ export class AutoNumbering implements IAction{
format:'',
prefix:'',
suffix:'',
verName:''
verName:{name:''}
}
globalThis.window.$format=this.format;
this.register();
@@ -56,8 +56,8 @@ export class AutoNumbering implements IAction{
const docNum = await this.createNumber(this.props);
record[this.props.field.code].value=docNum;
//変数設定
if(this.props.verName){
context.variables[this.props.verName]=docNum;
if(this.props.verName && this.props.verName.name!==''){
context.variables[this.props.verName.name]=docNum;
}
result= {
canNext:true,
@@ -84,6 +84,7 @@ export class AutoNumbering implements IAction{
execEval(match:string,expr:string):string{
console.log(match);
// @ts-ignore
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,18 +2,26 @@
import { actionAddins } from ".";
import $ from 'jquery';
import { IAction, IActionProperty, IActionNode, IActionResult } from "../types/ActionTypes";
import "./button-add.css";
/**
* ボタン配置属性定義
*/
interface IButtonAddProps {
//ボタン表示名
buttonName: string;
space?:ISpace;
//配置位置
position: string;
//イベント名
eventName:string
}
interface ISpace{
type:string,
elementId:string
}
export class ButtonAddAction implements IAction {
name: string;
actionProps: IActionProperty[];
@@ -47,43 +55,19 @@ export class ButtonAddAction implements IAction {
}
this.props = actionNode.ActionValue as IButtonAddProps;
//ボタンを配置する
const menuSpace = kintone.app.record.getHeaderMenuSpaceElement();
if(!menuSpace) return result;
if($("style#alc-button-add").length===0){
const css=`
.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;
}`;
const style = $("<style id='alc-button-add'>/<style>");
style.text(css);
$("head").append(style);
let buttonSpace;
if(this.props.space && this.props.space.elementId){
buttonSpace = kintone.app.record.getSpaceElement(this.props.space.elementId);
}else{
buttonSpace = kintone.app.record.getHeaderMenuSpaceElement();
}
if(!buttonSpace) return result;
const button =$(`<button id='${this.props.eventName}' class='alc-button-normal' >${this.props.buttonName}</button>`);
if(this.props.position==="一番左に追加する"){
$(menuSpace).prepend(button);
$(buttonSpace).prepend(button);
}else{
$(menuSpace).append(button);
$(buttonSpace).append(button);
}
const clickEventName = `${event.type}.customButtonClick.${this.props.eventName}`;
button.on("click",()=>{

View File

@@ -1,13 +1,13 @@
import { actionAddins } from ".";
import { IAction,IActionResult, IActionNode, IActionProperty, IContext } from "../types/ActionTypes";
import { IAction,IActionResult, IActionNode, IActionProperty, IContext, IVarName } from "../types/ActionTypes";
import { ConditionTree } from '../types/Conditions';
/**
* アクションの属性定義
*/
interface ICondition{
condition:string;
verName:string;
verName:IVarName;
}
/**
* 条件分岐アクション
@@ -21,7 +21,7 @@ export class ConditionAction implements IAction{
this.actionProps=[];
this.props={
condition:'',
verName:''
verName:{name:''}
}
//アクションを登録する
this.register();
@@ -58,8 +58,8 @@ export class ConditionAction implements IAction{
result:'いいえ'
}
}
if(this.props.verName){
context.variables[this.props.verName]=result.result;
if(this.props.verName && this.props.verName.name!==''){
context.variables[this.props.verName.name]=result.result;
}
return result;
}catch(error){

View File

@@ -6,7 +6,7 @@ import { IAction,IActionResult, IActionNode, IActionProperty, IField} from "../
interface IStrCountCheckProps{
field:IField;//チェックするフィールドの対象
message:string;//エラーメッセージ
strExpression:string;//
maxLength:number;//
}
/**
* 正規表現チェックアクション
@@ -21,7 +21,7 @@ export class StrCountCheckAciton implements IAction{
this.props={
field:{code:''},
message:'',
strExpression:''
maxLength:0
}
//アクションを登録する
this.register();
@@ -43,18 +43,16 @@ export class StrCountCheckAciton implements IAction{
if (!('field' in actionNode.ActionValue) && !('message' in actionNode.ActionValue) && !('strExpression'in actionNode.ActionValue)) {
return result
}
console.log(123);
this.props = actionNode.ActionValue as IStrCountCheckProps;
//条件式の計算結果を取得
const record = event.record;
const value = record[this.props.field.code].value;
let str = value.length
record.count.value = str
const regex = new RegExp(this.props.strExpression);
if(!regex.test(value)){
record[this.props.field.code].error > this.props.message.length ;
const maxLength = this.props.maxLength;
if(value === undefined || value === '' ){
return result;
}else if(maxLength < value.length){
record[this.props.field.code].error = this.props.message;
}else{
result= {
canNext:true,

View File

@@ -0,0 +1,66 @@
import { actionAddins } from ".";
import { IAction, IActionResult, IActionNode, IActionProperty, IField ,IContext, IVarName} from "../types/ActionTypes";
/**
* アクションの属性定義
*/
interface IDatetimeGetterProps {
/**変数の名前 */
verName:IVarName;
}
/**
* 現在日時を取得するアクション
*/
export class DatetimeGetterAction implements IAction {
name: string;
actionProps: IActionProperty[];
props: IDatetimeGetterProps;
constructor() {
this.name = "現在日時";
this.actionProps = [];
this.props = {
verName:{name:''}
}
this.register();
}
/**
* アクションの実行を呼び出す
* @param actionNode
* @param event
* @returns
*/
async process(actionNode: IActionNode, event: any,context:IContext): Promise<IActionResult> {
let result = {
canNext: true,
result: false
};
try {
//属性設定を取得する
this.actionProps = actionNode.actionProps;
if (!('verName' in actionNode.ActionValue) ) {
return result
}
this.props = actionNode.ActionValue as IDatetimeGetterProps;
let today = new Date();
if(this.props.verName && this.props.verName.name!==''){
context.variables[this.props.verName.name]=today.toISOString();
}
return result;
} catch (error) {
event.error = error;
console.error(error);
result.canNext = false;
return result;
}
};
register(): void {
actionAddins[this.name] = this;
}
}
new DatetimeGetterAction();

View File

@@ -56,8 +56,8 @@ export class FieldShownAction implements IAction{
}
}
result= {
canNext:true,
result:true
canNext:true,
result:true
}
return result;
}catch(error){
@@ -69,9 +69,9 @@ export class FieldShownAction implements IAction{
}
/**
*
*
* @param context 条件式を実行する
* @returns
* @returns
*/
getConditionResult(context:any):boolean{
const tree =this.getCondition(this.props.condition);
@@ -84,7 +84,7 @@ export class FieldShownAction implements IAction{
/**
* @param condition 条件式ツリーを取得する
* @returns
* @returns
*/
getCondition(condition:string):ConditionTree|null{
try{
@@ -93,7 +93,7 @@ export class FieldShownAction implements IAction{
if(tree.getConditions(tree.root).length>0){
return tree;
}else{
return null;
return null;
}
}catch(error){
return null;
@@ -103,6 +103,5 @@ export class FieldShownAction implements IAction{
register(): void {
actionAddins[this.name]=this;
}
}
new FieldShownAction();

View File

@@ -0,0 +1,507 @@
import { actionAddins } from ".";
import { IAction,IActionResult, IActionNode, IActionProperty, IField, IContext } from "../types/ActionTypes";
import { ConditionTree } from '../types/Conditions';
/**
* アクションの属性定義
*/
interface IInsertValueProps{
field:IField;
condition:string;
value:string;
show:string;
}
/**
*
*/
export class InsertValueAction implements IAction{
name: string;
actionProps: IActionProperty[];
props:IInsertValueProps;
constructor(){
this.name="値を挿入する";// DBに登録したアクション名
this.actionProps=[];
//プロパティ属性の初期化
this.props={
field:{code:''},
condition:'',
value:'',
show:''
}
//アクションを登録する
this.register();
}
/**
* 空白文字を空白文字が非対応のフィールドに挿入しようとしていないか、必須項目フィールドに挿入しようとしていないかチェックする
* @param {string} inputValue - 挿入する値
* @return {boolean} -入力値が有効な日付形式の場合はtrueを返し、そうでない場合は例外を発生させる
*/
checkInputBlank(fieldType :string | undefined,inputValue :string,fieldCode :string,fieldRequired :boolean | undefined,event :any): boolean{
//正規表現チェック
let blankCheck= inputValue.match(/^(\s| )+?$/);//半角スペース・タブ文字・改行・改ページ・全角スペース
if(blankCheck !== null){
//空白文字を空白文字が非対応のフィールドに挿入しようとしている場合、例外を発生させる
if(fieldType === "NUMBER" || fieldType === "DATE" || fieldType === "DATETIME" || fieldType === "TIME" || fieldType === "USER_SELECT"
|| fieldType === "ORGANIZATION_SELECT" || fieldType === "GROUP_SELECT" || fieldType === "RADIO_BUTTON" || fieldType === "DROP_DOWN" || fieldType === "CHECK_BOX" || fieldType === "MULTI_SELECT"){
event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドには、空白文字は挿入できません。"; //レコードにエラーを表示
throw new Error("「"+fieldCode+"」"+"フィールドには、空白文字は挿入できません。「値を挿入する」コンポーネントの処理を中断しました。");
//空白文字を必須項目フィールドに挿入しようとしている場合、例外を発生させる
}else if(fieldRequired){
event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドは必須項目のため、空白文字は挿入できません。"; //レコードにエラーを表示
throw new Error("「"+fieldCode+"」"+"フィールドは必須項目のため、空白文字は挿入できません。「値を挿入する」コンポーネントの処理を中断しました。");
}
}
return true;
}
/**
* 入力値が半角数字かチェックする関数
* @param {string} inputValue - 挿入する値
* @return {boolean} -入力値が有効な数値の場合はtrueを返し、そうでない場合は例外を発生させる
*/
checkInputNumber(inputValue :string,fieldCode :string,event :any): boolean{
let inputNumberValue = Number(inputValue);//数値型に変換
//有限数かどうか判定s
if(!isFinite(inputNumberValue)){
event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。"; //レコードにエラーを表示
throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、有効な数値ではありません。「値を挿入する」コンポーネントの処理を中断しました。");
}
return true;
}
/** 入力値が有効な日付形式かチェックする関数
* @param {string} inputValue - 挿入する値
* @return {boolean} -入力値が有効な日付形式の場合はtrueを返し、そうでない場合は例外を発生させる
*/
checkInputDate(inputValue :string,fieldCode :string,event :any): boolean{
//正規表現チェック
let twoDigitMonthDay = inputValue.match(/(\d{4})-(\d{2})-(\d{2})$/);//4桁の数字-2桁の数字-2桁の数字
let singleDigitMonthDay = inputValue.match(/(\d{4})-(\d{1})-(\d{1})$/);//4桁の数字-1桁の数字-2桁の数字
let singleDigitMonth = inputValue.match(/(\d{4})-(\d{1})-(\d{2})$/);//4桁の数字-1桁の数字-2桁の数字
let singleDigitDay = inputValue.match(/(\d{4})-(\d{2})-(\d{1})$/);//4桁の数字-2桁の数字-1桁の数字
let dateTime = inputValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).000Z/);//時刻入りのUTCの日付形式
let date;
//date型に変換
date = new Date(inputValue);
//date型変換できたか確認
if(date !== undefined && !isNaN(date.getDate())){
//正規表現チェック確認
if(twoDigitMonthDay === null && singleDigitMonth === null && singleDigitDay === null && singleDigitMonthDay === null && dateTime === null){
event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。"; //レコードにエラーを表示
throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。「値を挿入する」コンポーネントの処理を中断しました。");
}
}
return true;
}
/** 入力値が有効な時刻形式かチェックする関数
* @param {string} inputValue - 挿入する値
* @return {boolean} -入力値が有効な日付形式の場合はtrueを返し、そうでない場合は例外を発生させる
*/
checkInputTime(inputValue :string,fieldCode :string,event :any): boolean{
//正規表現チェック
let timeFormat =inputValue.match(/^([0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/);
//正規表現チェック確認
if(timeFormat === null){
event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な時刻形式です。"; //レコードにエラーを表示
throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な時刻形式です。「値を挿入する」コンポーネントの処理を中断しました。");
}
return true;
}
/**
* 入力値のフィールドタイプがDATETIMEであれば、時刻ありの日付形式変換し、DATEであれば時刻なしの日付形式変換する関数
* @param {string} inputValue -挿入する値
* @param {string} fieldType -フィールドタイプ
* @return {string} -入力値が日付形式に変換できた場合は文字列を返し、そうでない場合は例外を発生させる
*/
changeDateFormat(inputValue :string, fieldType :string,fieldCode :string,event :any): string{
let dateTime;
let date;
//挿入する値をdate型に変換
date = new Date(inputValue);
//date型変換できたか確認
if(date !== undefined && !isNaN(date.getDate())){
//日時フィールドの場合、時刻ありの日付形式変換
if(fieldType === "DATETIME"){
dateTime =date.toISOString();
return dateTime;
}
//日付フィールドの場合、時刻なしの日付形式変換
let dateArray=inputValue.match(/(\d{4})-(\d{1,2})-(\d{1,2})$/);//4桁の数字-12桁の数字-12桁の数字
if(dateArray !== null){
let yearIndex = 1;
let monthIndex = 2;
let dayIndex = 3;
let dateFormatted=`${dateArray[yearIndex]}-${dateArray[monthIndex]}-${dateArray[dayIndex]}`
return dateFormatted;
}
}
event.record[fieldCode]['error'] = "「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。"; //レコードにエラーを表示
throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした値は、無効な日付形式です。「値を挿入する」コンポーネントの処理を中断しました。");
}
/**
* 入力値がフィールドタイプ(ラジオボタン・ドロップダウン・複数選択・ドロップダウン)の選択肢に存在する値かチェックする関数
* @param {string} inputValue - 挿入する値
* @return {boolean} -入力値が有効な値の場合はtrueを返し、そうでない場合は例外を発生させる
*/
checkInputOption(inputValue :string,fieldOptions :string | undefined,fieldCode :string,event :any): boolean {
//入力値が選択肢に存在する値かチェックし、存在したらtrueを返す
if(fieldOptions !== undefined){
let options = Object.keys(fieldOptions);
for(var optionsIndex in options){
if(options[optionsIndex] === inputValue){
return true;
}
}
}
event.record[fieldCode]['error']="「"+fieldCode+"」"+"には、存在しない値を挿入しようとしたため、処理を中断しました。";
throw new Error("「"+fieldCode+"」"+"には、存在しない値を挿入しようとしたため、処理を中断しました。「値を挿入する」コンポーネントの処理を中断しました。");
}
/**
* 入力値がフィールドタイプ(ユーザー選択)で、ユーザー情報に存在する値かチェックする関数
* @param {string} inputValue - 挿入する値
* @return {string | boolean} 入力値が登録されているユーザー情報から見つかった場合、trueを返し、見つからなかった場合、falseを返す
*/
async setInputUser(inputValue :string): Promise<string | boolean>{
//ユーザー名を格納する変数
let usersName;
const usersInfoColumnIndex=0;
try{
//APIでユーザー情報を取得する
const resp =await kintone.api(kintone.api.url('/v1/users', true), 'GET', {codes:[inputValue ]})
//入力されたログイン名(メールアドレス)がユーザー情報に登録されている場合、そのユーザー名を取得する
if (resp.users[usersInfoColumnIndex].code === inputValue) {
usersName=resp.users[usersInfoColumnIndex].name;
}
//ユーザー名が取得できた場合、ログイン名とユーザー名をフィールドにセットする
if(usersName === undefined){
throw new Error();
}
}catch{
return false;
}
return usersName;
}
/**
* 入力値がフィールドタイプ(組織選択)で、組織情報に存在する値かチェックする関数
* @param {string} inputValue - 挿入する値
* @return {string | boolean} 入力値が登録されている組織情報から見つかった場合、trueを返し、見つからなかった場合、falseを返す
*/
async setInputOrganization(inputValue :string): Promise<string | boolean>{
//組織名を格納する変数
let organizationName;
const organizationsInfoColumnIndex=0;
try{
//APIで組織情報を取得する
const resp =await kintone.api(kintone.api.url('/v1/organizations.json', true), 'GET', {codes:[inputValue ]})
//入力された組織コードが組織情報に登録されている場合、その組織名を取得する
if (resp.organizations[organizationsInfoColumnIndex].code === inputValue) {
organizationName=resp.organizations[organizationsInfoColumnIndex].name;
}
//組織名が取得できた場合、組織コードと組織名をフィールドにセットする
if(organizationName === undefined){
throw new Error();
}
}catch{
return false;
}
return organizationName;
}
/**
* 入力値がフィールドタイプ(グループ選択)で、グループ情報に存在する値かチェックする関数
* @param {string} inputValue - 挿入する値
* @return {string | boolean} 入力値が登録されているグループ情報から見つかった場合、trueを返し、見つからなかった場合、falseを返す
*/
async setInputGroup(inputValue :string): Promise<string | boolean>{
//グループ名を格納する変数
let groupsName;
const groupsInfoColumnIndex=0;
try{
//APIでグループ情報を取得する
const resp =await kintone.api(kintone.api.url('/v1/groups.json', true), 'GET', {codes:[inputValue ]})
//入力されたグループコードがグループ情報に登録されている場合、そのグループ名を取得する
if (resp.groups[groupsInfoColumnIndex].code === inputValue) {
groupsName=resp.groups[groupsInfoColumnIndex].name;
}
//グループ名が取得できた場合、グループコードとグループ名をフィールドにセットする
if(groupsName === undefined){
throw new Error();
}
}catch{
return false;
}
return groupsName;
}
/**
* アクションの実行を呼び出す
* @param actionNode
* @param event
* @returns
*/
async process(actionNode:IActionNode,event:any,context:IContext):Promise<IActionResult> {
let result={
canNext:true,
result:false
};
try{
//属性設定を取得する
this.actionProps = actionNode.actionProps;
if (!('field' in actionNode.ActionValue) && !('value' in actionNode.ActionValue)) {
return result
}
const fieldColumnIndex=1;
const valueColumnIndex=3;
//プロパティで選択されたフィールド
const field=this.actionProps[fieldColumnIndex].props.modelValue.type;
//プロパティの挿入する値
const value=this.actionProps[valueColumnIndex].props.modelValue;
//条件式の結果を取得
const conditionResult = this.getConditionResult(context);
if(!conditionResult){
return result;
}
//プロパティの値を挿入するフィールドが未選択の場合、例外を発生させる
if(field === null){
throw new Error("「値を挿入する」コンポーネントで、値を挿入するフィールドが指定されていなかったため、処理が中断されました。");
}
//プロパティの値を挿入するフィールドが非対応フィールドの場合、例外を発生させる
//添付ファイル・テーブル・カテゴリー・ステータス・作成者・更新者・作業者・リビジョン番号・レコード番号・レコードID・計算・作成日時・更新日時フィールドが選択されている場合、例外を発生させる
if(field === "FILE" || field === "SUBTABLE" || field === "CATEGORY" || field === "STATUS"
|| field === "STATUS_ASSIGNEE" || field === "CREATOR" || field === "MODIFIER" || field === "__REVISION__"
|| field === "RECORD_NUMBER"|| field === "__ID__" || field ==="CALC" || field === "CREATED_TIME" || field === "UPDATED_TIME" ){
throw new Error("「値を挿入する」コンポーネントで、選択されたフィールドは、値を挿入するコンポーネントでは非対応のフィールドのため、処理を中断しました。");
}
//プロパティの挿入する値が未入力の場合、例外を発生させる
if(value === ""){
throw new Error("「値を挿入する」コンポーネントで、フィールドに挿入する値が指定されていなかったため、処理が中断されました。");
}
//既定のプロパティのインターフェースへ変換する
this.props = actionNode.ActionValue as IInsertValueProps;
//挿入する値を取得
let fieldValue = this.props.value;
//フィールドの種類を取得
const fieldType = this.props.field.type;
//フィールドが必須項目なのか取得
const fieldRequired=this.props.field.required;
//挿入するフィールドのコードを取得
const fieldCode=this.props.field.code;
//挿入する値の形式(手入力か変数)を取得
const insertValueType=this.props.show;
//ラジオボタン・チェックボックス・複数選択・ドロップダウンの選択肢を取得
let fieldOptions =this.props.field.options;
//変数の値を格納する
let variableValue;
//変数の場合、値が取得できるかチェック
if(insertValueType === "変数" && conditionResult){
variableValue = context.variables[fieldValue];
if(variableValue === undefined){
throw new Error("「"+fieldCode+"」"+"フィールドに入れようとした変数は、無効な入力形式です。");
}
fieldValue = variableValue;
}
//入力値チェック後、形式変換、型変換した値を格納する変数
let correctFormattedValue;
//入力値チェック後、形式変換、型変換した値を格納する配列
let correctValues :string[] = [];
//入力エラー(空白文字の混入)がないことをチェック
let notInputError=this.checkInputBlank(fieldType,fieldValue,fieldCode,fieldRequired,event);
//条件式の結果がtrue、入力エラー空白文字の混入がない場合、挿入する値をフィールドタイプ別にチェックする
if(conditionResult && notInputError){
//文字列型のフィールドに挿入しようとしている値が適切の場合、correctFormattedValueに代入する
if(fieldType === "SINGLE_LINE_TEXT" || fieldType === "MULTI_LINE_TEXT" || fieldType === "RICH_TEXT" || fieldType === "LINK" ){
correctFormattedValue = fieldValue;
//数値型のフィールドに挿入しようとしている値が適切の場合、数値型に型変換してcorrectFormattedValueに代入する
}else if(fieldType === "NUMBER" ){
if(this.checkInputNumber(fieldValue,fieldCode,event)){//入力値チェック
correctFormattedValue = Number(fieldValue);//型変換
}
//日付・日時型のフィールドに挿入しようとしている値が適切の場合、指定の日付・日時に形式変換してcorrectFormattedValueに代入する
}else if(fieldType === "DATE" || fieldType === "DATETIME" ){
if(this.checkInputDate(fieldValue,fieldCode,event)){//入力値チェック
let formattedDate = this.changeDateFormat(fieldValue,fieldType,fieldCode,event)
if(formattedDate){
correctFormattedValue = formattedDate
}
}
//時刻フィールドに挿入しようとしている値が適切の場合、correctFormattedValueに代入する
}else if(fieldType === "TIME"){
if(this.checkInputTime(fieldValue,fieldCode,event)){//入力値チェック
correctFormattedValue = fieldValue;
}
//ラジオボタン・ドロップダウンのフィールドの選択肢と入力値が一致した場合、correctFormattedValueに代入する
}else if(fieldType === "RADIO_BUTTON" || fieldType === "DROP_DOWN"){
if(this.checkInputOption(fieldValue,fieldOptions,fieldCode,event)){//入力値チェック
correctFormattedValue = fieldValue;
}
//チェックボックス・複数選択のフィールドの選択肢と入力値が一致した場合、correctValuesの配列に代入する
}else if(fieldType === "CHECK_BOX" || fieldType === "MULTI_SELECT" ){
if(this.checkInputOption(fieldValue,fieldOptions,fieldCode,event)){//入力値チェック
correctValues[0] = fieldValue;
}
//ユーザー情報フィードに挿入しようとした値が適切な場合、correctFormattedValueに代入する
}else if(fieldType === "USER_SELECT"){
//挿入する値がユーザー情報から見つかれば、ユーザー名を格納
let users=await this.setInputUser(fieldValue);
//ユーザー名が格納できている場合、ログイン名とユーザー名をcorrectFormattedValueに代入する
if(!users){
event.record[fieldCode]['error']="ユーザー選択に、挿入しようとしたユーザー情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。";
throw new Error("ユーザー選択に、挿入しようとしたユーザー情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。");
}else{
correctFormattedValue=[{ code: fieldValue, name: users }];
}
//組織情報フィードに挿入しようとした値が適切な場合、correctFormattedValueに代入する
}else if(fieldType === "ORGANIZATION_SELECT"){
//挿入する値が組織情報から見つかれば、組織名を格納
let organizations=await this.setInputOrganization(fieldValue);
//組織名が格納できている場合、組織コードと組織名をcorrectFormattedValueに代入する
if(!organizations){
event.record[fieldCode]['error']="組織選択フィールドに、挿入しようとした組織情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。";
throw new Error("組織選択フィールドに、挿入しようとした組織情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。");
}else{
correctFormattedValue=[{ code: fieldValue, name: organizations}];
}
//グループ情報フィードに挿入しようとした値が適切な場合、correctFormattedValueに代入する
}else if(fieldType === "GROUP_SELECT"){
//挿入する値がグループ情報から見つかれば、グループ名を格納
let groups=await this.setInputGroup(fieldValue);
//グループ名が格納できている場合、グループコードとグループ名をcorrectFormattedValueに代入する
if(!groups){
event.record[fieldCode]['error']="グループ選択フィールドに、挿入しようとしたグループ情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。";
throw new Error("グループ選択フィールドに、挿入しようとしたグループ情報は見つかりませんでした。「値を挿入する」コンポーネントの処理を中断しました。");
}else{
correctFormattedValue=[{ code: fieldValue, name: groups}];
}
}
}
//条件式の結果がtrueかつ挿入する値が変換できた場合、フィールドラジオボタン・ドロップダウン・チェックボックス・複数選択・文字列一行・文字列複数行・リッチエディタ・数値・日付・日時・時刻にセット
if(conditionResult && (correctFormattedValue || correctValues)){
//条件式の結果がtureかつ、値を正しい形式に変換できた場合、フィールドに値をセットする
if(correctFormattedValue){
event.record[fieldCode].value = correctFormattedValue;
//条件式の結果がtureかつ、値を正しい形式配列に変換できた場合、フィールドに値配列をセットする
}else if(correctValues.length > 0){
event.record[fieldCode].value = correctValues;
}
}
result= {
canNext:true,
result:true
}
return result;
}catch(error:any){
event.record;
event.error=error.message;
console.error(error);
result.canNext=true;//次のノードは処理を続ける
return result;
}
}
/**
*
* @param context 条件式を実行する
* @returns
*/
getConditionResult(context:any):boolean{
//プロパティ`condition`から条件ツリーを取得する
const tree =this.getCondition(this.props.condition);
if(!tree){
//条件を設定されていません
return true;
}
return tree.evaluate(tree.root,context);
}
/**
* @param condition 条件式ツリーを取得する
* @returns
*/
getCondition(condition:string):ConditionTree|null{
try{
const tree = new ConditionTree();
tree.fromJson(condition);
if(tree.getConditions(tree.root).length>0){
return tree;
}else{
return null;
}
}catch(error){
return null;
}
}
register(): void {
actionAddins[this.name]=this;
}
}
new InsertValueAction();

View File

@@ -6,6 +6,7 @@ import { IAction, IActionResult, IActionNode, IActionProperty, IField } from "..
interface IMailCheckProps {
field: IField;//チェックするフィールドの対象
message: string;//エラーメッセージ
emailCheck:string;
}
/**
* メールアドレスチェックアクション
@@ -20,7 +21,7 @@ export class MailCheckAction implements IAction {
this.props = {
field: { code: '' },
message: '',
emailCheck:''
}
//アクションを登録する
this.register();
@@ -37,34 +38,25 @@ export class MailCheckAction implements IAction {
result: false
};
try {
//属性設定を取得する
this.actionProps = actionNode.actionProps;
const emailAction = this.actionProps.find(obj => obj.props.name === 'emailcheck')
if (!('field' in actionNode.ActionValue) && !('message' in actionNode.ActionValue) && !!!emailAction) {
if (!('field' in actionNode.ActionValue) && !('message' in actionNode.ActionValue) && !('emailCheck' in actionNode.ActionValue)) {
return result
}
console.log(actionNode);
this.props = actionNode.ActionValue as IMailCheckProps;
//条件式の計算結果を取得
const record = event.record;
const value = record[this.props.field.code].value;
if (emailAction?.props.modelValue === '厳格') {
if (!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value)) {
console.log('厳格');
if (this.props.emailCheck === '厳格') {
if (!/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value)) {
record[this.props.field.code].error = this.props.message;
}
} else if (emailAction?.props.modelValue === 'ゆるめ') {
if (!/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value)) {
console.log('ゆるめ');
} else if (this.props.emailCheck === 'ゆるめ') {
if (!/^[^@]+@[^@]+$/.test(value)) {
record[this.props.field.code].error = this.props.message;
}
} else {
result = {
@@ -72,7 +64,6 @@ export class MailCheckAction implements IAction {
result: true
}
}
console.log(record[this.props.field.code]);
return result;
} catch (error) {
event.error = error;

View File

@@ -0,0 +1,211 @@
import { actionAddins } from ".";
import { IField, IAction,IActionResult, IActionNode, IActionProperty } from "../types/ActionTypes";
import { Formatter } from "../util/format";
//右UI画面propertyのname:型:
interface IStringJoinProps{
//保存先フィールド
saveField:IField;
//結合元フィールド1
joinField1:IField;
//結合元フィールド2
joinField2:IField;
//区切り文字
delimiter:string;
}
//IActionインタフェースを実装する新しいクラスActionを作成
export class StringJoinAction implements IAction{
name: string;
//importから導入顕示定義
actionProps: IActionProperty[];
//上方のinterface Propsから、props受ける属性を定義
props:IStringJoinProps;
//関数定義に必要な類名を構築:
constructor(){
//pgAdminDBに登録したアクション名(name/subtitle)一致する必要がある:
this.name="文字結合";
this.actionProps=[];
this.register();
//プロパティ属性初期化:
this.props={
saveField:{code:''},
joinField1:{code:''},
joinField2:{code:''},
delimiter:''
}
//リセット上記登録表:
this.register();
}
/**
* アクションの処理を実装する
* @param actionNode アクションノード
* @param event Kintoneのイベント
* @param context コンテキスト(レコード、変数情報を持っている)
* @returns
*/
//非同期処理ある関数下のある属性:
async process(actionNode:IActionNode,event:any):Promise<IActionResult> {
let result={
//後継処理不可:
canNext:false,
result:false
};
try{
//属性設定を取得する:
this.actionProps=actionNode.actionProps;
//プロパティ設定のデータ型は必要な情報含めますか全部不存在時return:
if (!('saveField' in actionNode.ActionValue) && !('joinField1' in actionNode.ActionValue) && !('joinField2' in actionNode.ActionValue)) {
return result
}
//既定のプロパティのインタフェースへ変換:
this.props = actionNode.ActionValue as IStringJoinProps;
const record = event.record;
//kintoneフィールドタイプ取得
const joinField1type=this.props.joinField1.type;
const joinField2type=this.props.joinField2.type;
const saveFieldtype=this.props.saveField.type;
//////////////////////////////////////////////////////////////////////////////////////////////////////
// //保存先フィールドは文字列フィールドではない場合、エラー発生:
if(!(saveFieldtype==='SINGLE_LINE_TEXT'||saveFieldtype==='MULTI_LINE_TEXT'||saveFieldtype==='RICH_TEXT')){
event.error='[エラーメッセージ]:結合保存先対応不可。結合しません';
if (event.type.includes('success')){
window.alert("[windows alert]"+event.error);
}
result = {
canNext: false,
result: false
}
return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
//値取得方法定義:
function getValue(value:string,type:string|undefined,fieldCode:string,event:any){
if(event.record[fieldCode]?.value===undefined||event.record[fieldCode]?.value===null){
event.record[fieldCode].value='';
}
//作成者、更新者:
if(type==='CREATOR'||type==='MODIFIER'){
value = event.record[fieldCode]?.value.name;
//日時、作成日時、更新日時:
}else if(type==='DATETIME'||type==='CREATED_TIME'||type==='UPDATED_TIME'){
if(event.record[fieldCode]?.value!==undefined && event.record[fieldCode]?.value!==''){
value = Formatter.dateFormat(new Date(event.record[fieldCode]?.value),'yyyy-MM-dd HH:mm');
}else{
value=event.record[fieldCode]?.value;
}
//ユーザ選択、組織選択、グループ選択、添付ファイル名、作業者、カテゴリー:
}else if(type==='USER_SELECT'||type==='ORGANIZATION_SELECT'||type==='GROUP_SELECT'||type==='FILE'||type==='STATUS_ASSIGNEE'){
if(event.record[fieldCode]?.value===undefined || event.record[fieldCode]?.value===''){
value = event.record[fieldCode]?.value;
}else{
const mototext=event.record[fieldCode]?.value;
let arr=[];
for(let i=0;i<mototext.length;i++){
arr.push(mototext[i].name);
}
//配列要素を,で連結して文字列を作成:
value=arr.join();
}
//カテゴリー、チェックボックス、複数選択:
}else if(type==='CATEGORY'||type==='CHECK_BOX'||type==='MULTI_SELECT'){
if(event.record[fieldCode]?.value===undefined || event.record[fieldCode]?.value===''){
value = event.record[fieldCode]?.value;
}else{
const mototext=event.record[fieldCode]?.value;
let arr=[];
for(let i=0;i<mototext.length;i++){
arr.push(mototext[i]);
}
//配列要素を,で連結して文字列を作成:
value=arr.join();
}
//詳細画面プロセス実行後のステータス:
}else if(type==='STATUS'&&event.type.includes('process')){
value = event.nextStatus.value;
}else{
value = event.record[fieldCode]?.value;
}
if (value===undefined || value===null){
value='';
}
return value;
}
//////////////////////////////////////////////////////////////////////
//値取得方法呼出:
let joinValue1:string='';
joinValue1=getValue(joinValue1,joinField1type,this.props.joinField1.code,event);
/////////////////////////////////////////////////////////////////////////////////////
let joinValue2:string='';
joinValue2=getValue(joinValue2,joinField2type,this.props.joinField2.code,event);
//////////////////////////////////////////////////////////////////////////////////////////////////////////
const conString = this.props.delimiter;
let saveValue:string='';
//前後結合元が空白なら区切り文字も空白にする(例:1-8の8無いなら1。1-8の1無いなら8。1空白8の8無いなら1。結合元全部空白なら全部空白):
if(joinValue1===''&&joinValue2===''){
saveValue='';
}else if(joinValue1===''&&joinValue2!==''){
saveValue=joinValue2;
}else if(joinValue2===''&&joinValue1!==''){
saveValue=joinValue1;
}else if(joinValue1!==''&&joinValue2!==''){
saveValue=`${joinValue1}${conString}${joinValue2}`
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//新規/更新/一覧保存成功後の以外のeventでPUT使用しない
if (!event.type.includes('success')){
//保存先フィールドに値セット:
record[this.props.saveField.code].value=saveValue;
window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。");
}else{
const params={
"app":event.appId,
"id":event.recordId,
"record":{[this.props.saveField.code]:{"value":saveValue}}
};
return await kintone.api(kintone.api.url('/k/v1/record',true),'PUT',params).then((resp) => {
//kintone保存先フィールド存在確認
record[this.props.saveField.code].value=saveValue;
if (event.type.includes('index')){
window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。一覧画面更新成功後自動リロードしません。必要に応じて手動リロードください。");
}else{
window.alert("文字結合行いました。"+this.props.joinField1.name+":"+joinValue1+","+this.props.joinField2.name+":"+joinValue2+"。");
}
//一覧画面更新成功後リロード:
// if (event.type.includes('index')){
// event.url = location.href.endsWith('/') || location.href.endsWith('&') ?
// location.href.slice(0, -1) :
// location.href + (location.href.includes('?') ? '&' : '/');
// }
}).catch((error) => {
event.error = 'エラーが発生しました。結合しません。システム管理者へお問合せください';
window.alert(event.error+"error message"+error);
return event;
});
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
result= {
canNext:true,
result:true
}
return result;
}catch(error){;
if (event.type.includes('success')){
window.alert("[windows alert]処理中異常が発生しました。結合しません。システム担当者へお問合せください。errorメッセージ"+error)
}
event.error="[エラーメッセージ]処理中異常が発生しました。結合しません。システム担当者へお問合せください。errorメッセージ"+error;
return {
canNext:false,
result:false
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
register(): void {
actionAddins[this.name]=this;
}
}
new StringJoinAction();

View File

@@ -0,0 +1,96 @@
import { actionAddins } from ".";
import { IAction,IActionResult, IActionNode, IActionProperty, IField, IContext } from "../types/ActionTypes";
//クラス名を設計書に揃える
/**
* アクションの属性定義
*/
interface FullWidthProps{
//checkOption:Array<string>,
field:IField
}
/**
* 全角チェックアクション
*/
export class FullWidthAction implements IAction{
name: string;
actionProps: IActionProperty[];
props:FullWidthProps;
constructor(){
this.name="全角チェック"; /* pgadminのnameと同様 */
this.actionProps=[];
this.props={
//checkOption:[],
field:{code:''}
}
//アクションを登録する
this.register();
}
/**
* アクションの実行を呼び出す
* @param actionNode
* @param event
* @returns
*/
async process(actionNode:IActionNode,event:any,context:IContext):Promise<IActionResult> {
let result={
canNext:true,
result:false
};
try{
//属性設定を取得する
this.actionProps=actionNode.actionProps;
if (!('field' in actionNode.ActionValue) ) {
return result
}
this.props = actionNode.ActionValue as FullWidthProps;
//条件式の計算結果を取得
const record = event.record;
const value = record[this.props.field.code]?.value;
//条件分岐
//未入力時は何も処理をせず終了
if(value===undefined || value===''){
return result;
}
//半角が含まれていた場合resultがfalse
if(!this.containsFullWidthChars(value)){
//エラー時に出力される文字設定
record[this.props.field.code].error="半角が含まれています";
//次の処理を中止する値設定
result.canNext=false;
return result;
}
//resultプロパティ指定
result= {
canNext:true,
result:true
}
return result;
//例外処理
}catch(error){
event.error=error;
console.error(error);
result.canNext=false;
return result;
}
}
// 全て全角の文字列の場合はtrue、そうでない場合はfalse
containsFullWidthChars(text: string): boolean {
// 半角英数字カナ記号を除外
const checkRegex="^[^\x01-\x7E\uFF61-\uFF9F]+$";
//正規表現オブジェクト生成
const fullWidthRegex = new RegExp(checkRegex);
//正規表現チェック
return fullWidthRegex.test(text);
}
//戻り値を持たないためvoid型
register(): void {
actionAddins[this.name]=this;
}
}
new FullWidthAction();

View File

@@ -0,0 +1,90 @@
import { actionAddins } from ".";
import { IAction,IActionResult, IActionNode, IActionProperty, IField, IContext } from "../types/ActionTypes";
/**
* アクションの属性定義
*/
interface HalfWidthProps{
field:IField
}
/**
* 半角チェックアクション
*/
export class HalfWidthAction implements IAction{
name: string;
actionProps: IActionProperty[];
props:HalfWidthProps;
constructor(){
this.name="半角チェック"; /* pgadminのnameと同様 */
this.actionProps=[];
this.props={
field:{code:''}
}
//アクションを登録する
this.register();
}
/**
* アクションの実行を呼び出す
* @param actionNode
* @param event
* @returns
*/
async process(actionNode:IActionNode,event:any,context:IContext):Promise<IActionResult> {
let result={
canNext:true,
result:false
};
try{
//属性設定を取得する
this.actionProps=actionNode.actionProps;
if (!('field' in actionNode.ActionValue) ) {
return result
}
this.props = actionNode.ActionValue as HalfWidthProps;
//条件式の計算結果を取得
const record = event.record;
const value = record[this.props.field.code]?.value;
//条件分岐
//未入力時は何も処理をせず終了
if(value===undefined || value===''){
return result;
}
//全角が含まれていた場合保存処理中止(エラー処理)
if(!this.containsHalfWidthChars(value)){
//エラー時に出力される文字設定
record[this.props.field.code].error="全角が含まれています";
//次の処理を中止する値設定
result.canNext=false;
return result;
}
//半角の場合問題なく実行
//resultプロパティ指定
result= {
canNext:true,
result:true
}
return result;
//例外処理
}catch(error){
event.error=error;
console.error(error);
result.canNext=false;
return result;
}
}
// 全て全角の文字列の場合はtrue、そうでない場合はfalse
containsHalfWidthChars(text: string): boolean {
const checkRegex = "^[\x01-\x7E\uFF61-\uFF9F]+$";
//正規表現オブジェクト生成
const halfWidthRegex = new RegExp(checkRegex);
//正規表現チェック
return halfWidthRegex.test(text);
}
//戻り値を持たないためvoid型
register(): void {
actionAddins[this.name]=this;
}
}
new HalfWidthAction();

View File

@@ -0,0 +1,70 @@
import { actionAddins } from ".";
import { IAction,IActionResult, IActionNode, IActionProperty, IField, IContext, IVarName} from "../types/ActionTypes";
/**
* アクションの属性定義
*/
interface IGetValueProps{
field:IField;//チェックするフィールドの対象
verName:IVarName;
}
/**
* 正規表現チェックアクション
*/
export class GetValueAciton implements IAction{
name: string;
actionProps: IActionProperty[];
props:IGetValueProps;
constructor(){
this.name="値を取得する";
this.actionProps=[];
this.props={
field:{code:''},
verName:{name:''}
}
//アクションを登録する
this.register();
}
/**
* アクションの実行を呼び出す
* @param actionNode
* @param event
* @returns
*/
async process(actionNode:IActionNode,event:any,context:IContext):Promise<IActionResult> {
let result={
canNext:true,
result:false
};
try{
//属性設定を取得する
this.actionProps=actionNode.actionProps;
if (!('field' in actionNode.ActionValue) && !('verName' in actionNode.ActionValue)) {
return result
}
this.props = actionNode.ActionValue as IGetValueProps;
//条件式の計算結果を取得
const record = event.record;
const value = record[this.props.field.code].value;
if(this.props.verName && this.props.verName.name!==''){
context.variables[this.props.verName.name] = value;
}
result = {
canNext:true,
result:true
}
return result;
}catch(error){
event.error=error;
console.error(error);
result.canNext=false;
return result;
}
};
register(): void {
actionAddins[this.name]=this;
}
}
new GetValueAciton();

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 { ActionProcess } from './types/action-process';
import { ActionFlow } from './types/ActionTypes';

View File

@@ -89,6 +89,13 @@ export interface IField{
name?:string;
code:string;
type?:string;
required?:boolean;
options?:string;
}
//変数のインターフェース
export interface IVarName{
name:string;
fields?:IVarName[];
}
/**

View File

@@ -9,6 +9,13 @@ import '../actions/condition-action';
import '../actions/regular-check';
import '../actions/mail-check';
import '../actions/counter-check';
import '../actions/datetime-getter';
import '../actions/insert-value';
import '../actions/value-getter';
import '../actions/string-join';
import '../actions/validation-fullwidth';
import '../actions/validation-halfwidth';
import { ActionFlow,IActionFlow, IActionResult,IContext } from "./ActionTypes";
export class ActionProcess{
@@ -42,7 +49,7 @@ export class ActionProcess{
result = await action.process(nextAction,this.event,this.context);
}
let nextInput = '';
//outputPoints一以上の場合、次のInputPoint戻り値を設定
//outputPoints一以上㝮場坈〝次㝮InputPoint戻り値を設定
if(nextAction.outputPoints && nextAction.outputPoints.length>1){
nextInput = result.result||'';
}

View File

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

View File

@@ -2,11 +2,160 @@
# 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":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622"
integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==
"@esbuild/android-arm@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682"
integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==
"@esbuild/android-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2"
integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==
"@esbuild/darwin-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1"
integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==
"@esbuild/darwin-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d"
integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==
"@esbuild/freebsd-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54"
integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==
"@esbuild/freebsd-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e"
integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==
"@esbuild/linux-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0"
integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==
"@esbuild/linux-arm@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0"
integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==
"@esbuild/linux-ia32@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7"
integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==
"@esbuild/linux-loong64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d"
integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==
"@esbuild/linux-mips64el@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231"
integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==
"@esbuild/linux-ppc64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb"
integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==
"@esbuild/linux-riscv64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6"
integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==
"@esbuild/linux-s390x@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071"
integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==
"@esbuild/linux-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338"
integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==
"@esbuild/netbsd-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1"
integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==
"@esbuild/openbsd-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae"
integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==
"@esbuild/sunos-x64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d"
integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==
"@esbuild/win32-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9"
integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==
"@esbuild/win32-ia32@0.18.20":
version "0.18.20"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102"
integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==
"@esbuild/win32-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz"
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":
version "3.5.24"
resolved "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.24.tgz"
@@ -14,7 +163,7 @@
dependencies:
"@types/sizzle" "*"
"@types/node@^20.8.9", "@types/node@>= 14":
"@types/node@^20.8.9":
version "20.11.0"
resolved "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz"
integrity sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==
@@ -26,6 +175,32 @@
resolved "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.5.tgz"
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:
version "3.1.3"
resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz"
@@ -34,11 +209,31 @@ anymatch@~3.1.2:
normalize-path "^3.0.0"
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:
version "2.2.0"
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz"
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:
version "3.0.2"
resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz"
@@ -46,6 +241,23 @@ braces@~3.0.2:
dependencies:
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":
version "3.5.3"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
@@ -61,6 +273,55 @@ braces@~3.0.2:
optionalDependencies:
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:
version "0.18.20"
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz"
@@ -89,6 +350,29 @@ esbuild@^0.18.10:
"@esbuild/win32-ia32" "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:
version "7.0.1"
resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz"
@@ -96,13 +380,49 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"
glob-parent@~5.1.2:
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:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
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:
version "4.3.4"
resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz"
@@ -137,6 +457,40 @@ jquery@^3.7.1:
resolved "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz"
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:
version "3.3.6"
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz"
@@ -147,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"
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:
version "1.0.0"
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz"
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"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@@ -166,6 +532,11 @@ postcss@^8.4.27:
picocolors "^1.0.0"
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:
version "3.6.0"
resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz"
@@ -173,6 +544,11 @@ readdirp@~3.6.0:
dependencies:
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:
version "3.29.4"
resolved "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz"
@@ -180,7 +556,14 @@ rollup@^3.27.1:
optionalDependencies:
fsevents "~2.3.2"
sass@*, sass@^1.69.5:
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:
version "1.69.7"
resolved "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz"
integrity sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==
@@ -189,11 +572,42 @@ sass@*, sass@^1.69.5:
immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0"
source-map-js@^1.0.2, "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:
version "1.0.2"
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz"
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:
version "5.0.1"
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
@@ -201,6 +615,11 @@ to-regex-range@^5.0.1:
dependencies:
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:
version "5.2.2"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz"
@@ -211,6 +630,37 @@ undici-types@~5.26.4:
resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz"
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:
version "4.5.0"
resolved "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz"
@@ -222,6 +672,50 @@ vite@^4.4.5:
optionalDependencies:
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:
version "1.22.22"
resolved "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz"

View File

@@ -1,55 +1,22 @@
[
{
"component": "InputText",
"props": {
"displayName": "文字入力",
"modelValue": "",
"name": "str",
"placeholder": "文字を入力してください",
"maxLength":"20",
"hint":"文字列入力<br>入力ルール指定可能。ルールの設定例:[val=>!!val||'必須入力です']",
"rules":"[val=>!!val||'必須入力です']"
}
},
{
"component": "AppFieldSelect",
"props": {
"displayName": "フィールド選択(複数)",
"modelValue": {},
"name": "selectFields",
"placeholder": "アプリ選択後、フィールドを選んでください",
"selectType":"multiple"
}
},
{
"component": "AppFieldSelect",
"props": {
"displayName": "フィールド選択(単一)",
"modelValue": {},
"name": "selectField",
"placeholder": "アプリ選択後、フィールドを選んでください",
"selectType":"single"
}
},
{
"component": "ColorPicker",
"props": {
"displayName": "色選択",
"modelValue": "",
"name": "color",
"placeholder": "カラーを選択してください"
}
},
{
"component": "NumInput",
"props": {
"displayName": "数値入力フィールド",
"modelValue": "",
"name": "num",
"max":100,
"min":0,
"placeholder": "数値を入力してください",
"rules":"[val=>!!val ||'数値を入力してください',val=>val<=100 && val>=1 || '1-100の範囲内の数値を入力してください']"
}
{
"component": "FieldInput",
"props": {
"displayName": "フィールド",
"modelValue": {},
"name": "field",
"placeholder": "対象項目を選択してください"
}
]
},
{
"component": "SelectBox",
"props": {
"displayName": "チェックする全角文字",
"modelValue": null,
"name": "options",
"placeholder": "チェックしたい全角文字を選択する",
"selectType":"multiple",
"options":["全角記号および句読点","ひらがな","カタカナ","全角英数字","常用漢字","拡張漢字"]
}
}
]