Compare commits
2 Commits
feature/em
...
mvp_step2_
| Author | SHA1 | Date | |
|---|---|---|---|
| 58e22dc55f | |||
| f861955b51 |
1
backend/.gitignore
vendored
1
backend/.gitignore
vendored
@@ -56,7 +56,6 @@ coverage.xml
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
*.log.*
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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=
|
||||
)
|
||||
@@ -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
@@ -31,6 +31,8 @@ def getkintoneformat():
|
||||
|
||||
|
||||
def createkintonefields(property,value,trueformat):
|
||||
if(type(value) == str):
|
||||
value = value.replace("\"","⊡⊡")
|
||||
p = []
|
||||
if(property=="options"):
|
||||
o=[]
|
||||
@@ -148,7 +150,7 @@ def getfieldsfromexcel(df,mapping):
|
||||
|
||||
|
||||
col.append(f"\"{df.iloc[row,codecolumn]}\":{{{','.join(p)}}}")
|
||||
fields = ",".join(col).replace("\\", "\\\\")
|
||||
fields = ",".join(col).replace("\\", "\\\\").replace("⊡⊡","\\\"")
|
||||
return json.loads(f"{{{fields}}}")
|
||||
|
||||
def getsettingfromexcel(df):
|
||||
@@ -544,7 +546,7 @@ async def createappfromexcel(request:Request,files:t.List[UploadFile] = File(...
|
||||
if app.get("revision") != None:
|
||||
result["revision"] = app["revision"]
|
||||
app = addfieldstokintone(result["app"],fields,env)
|
||||
if len(processes)> 0:
|
||||
if len(processes["states"])> 0:
|
||||
app = updateprocesstokintone(result["app"],processes,env)
|
||||
if app.get("revision") != None:
|
||||
result["revision"] = app["revision"]
|
||||
|
||||
@@ -13,7 +13,6 @@ 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"
|
||||
|
||||
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"]
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
SECRET_KEY = "alicorns"
|
||||
ALGORITHM = "HS256"
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES = 2880
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES = 30
|
||||
|
||||
|
||||
def get_password_hash(password: str) -> str:
|
||||
@@ -25,7 +25,7 @@ def create_access_token(*, data: dict, expires_delta: timedelta = None):
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||
expire = datetime.utcnow() + timedelta(minutes=2880)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -279,8 +279,7 @@ def get_events(db: Session):
|
||||
return events
|
||||
|
||||
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()
|
||||
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()
|
||||
if not eveactions:
|
||||
raise HTTPException(status_code=404, detail="Data not found")
|
||||
return eveactions
|
||||
|
||||
@@ -85,7 +85,6 @@ class Event(Base):
|
||||
eventid= Column(String(100), nullable=False)
|
||||
function = Column(String(500), nullable=False)
|
||||
mobile = Column(Boolean, default=False)
|
||||
eventgroup = Column(Boolean, default=False)
|
||||
|
||||
class EventAction(Base):
|
||||
__tablename__ = "eventaction"
|
||||
|
||||
@@ -137,7 +137,6 @@ class Event(Base):
|
||||
eventid: str
|
||||
function: str
|
||||
mobile: bool
|
||||
eventgroup: bool
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,147 +0,0 @@
|
||||
<mxfile host="app.diagrams.net" modified="2024-02-21T05:42:02.026Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36" etag="T2S5cjvthSOlO5DmGw-C" version="23.1.5" type="device">
|
||||
<diagram id="Z6uZM46JtkVaKDzPjE9h" name="サイトマップ">
|
||||
<mxGraphModel dx="1434" dy="820" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-14" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-1" target="Gi77RX5G2m4J9-6cMje4-13" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-1" value="テナント登録" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.login;" parent="1" vertex="1">
|
||||
<mxGeometry x="60" y="50" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-2" value="Admin Login" style="html=1;whiteSpace=wrap;strokeColor=#2D7600;fillColor=#60a917;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#ffffff;sketch=0;shape=mxgraph.sitemap.login;" parent="1" vertex="1">
|
||||
<mxGeometry x="60" y="270" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-8" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-5" target="Gi77RX5G2m4J9-6cMje4-7" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-9" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-5" target="Gi77RX5G2m4J9-6cMje4-7" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-12" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-5" target="Gi77RX5G2m4J9-6cMje4-11" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-5" value="Home" style="html=1;whiteSpace=wrap;strokeColor=#2D7600;fillColor=#60a917;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#ffffff;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="240" y="270" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="Gi77RX5G2m4J9-6cMje4-2" target="Gi77RX5G2m4J9-6cMje4-5" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-42" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-7" target="Gi77RX5G2m4J9-6cMje4-41" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-7" value="ユーザー登録" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="440" y="220" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-11" value="ドメイン登録" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="440" y="340" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-13" value="テナント管理者作成" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.login;" parent="1" vertex="1">
|
||||
<mxGeometry x="240" y="50" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-15" value="ライセンス情報" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" parent="1" vertex="1">
|
||||
<mxGeometry x="480" y="10" width="90" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-16" value="Adminユーザー" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" parent="1" vertex="1">
|
||||
<mxGeometry x="480" y="90" width="90" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="Gi77RX5G2m4J9-6cMje4-13" target="Gi77RX5G2m4J9-6cMje4-15" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="Gi77RX5G2m4J9-6cMje4-13" target="Gi77RX5G2m4J9-6cMje4-16" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-19" value="テナントDB<br>作成" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" parent="1" vertex="1">
|
||||
<mxGeometry x="550" y="50" width="90" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-20" target="Gi77RX5G2m4J9-6cMje4-21" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-20" value="Login" style="html=1;whiteSpace=wrap;strokeColor=#005700;fillColor=#008a00;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;sketch=0;shape=mxgraph.sitemap.login;fontColor=#ffffff;" parent="1" vertex="1">
|
||||
<mxGeometry x="50" y="610" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-21" target="Gi77RX5G2m4J9-6cMje4-25" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="430" y="645" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-21" value="Home" style="html=1;whiteSpace=wrap;strokeColor=#005700;fillColor=#008a00;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#ffffff;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="230" y="610" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-27" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-25" target="Gi77RX5G2m4J9-6cMje4-26" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-25" value="アプリ一覧" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.news;" parent="1" vertex="1">
|
||||
<mxGeometry x="440" y="610" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-29" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-26" target="Gi77RX5G2m4J9-6cMje4-28" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-26" value="フロー一覧" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.news;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="610" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-40" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-28" target="Gi77RX5G2m4J9-6cMje4-39" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-28" value="フローエディタ" style="html=1;whiteSpace=wrap;strokeColor=#005700;fillColor=#008a00;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#ffffff;sketch=0;shape=mxgraph.sitemap.news;" parent="1" vertex="1">
|
||||
<mxGeometry x="800" y="610" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-33" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-30" target="Gi77RX5G2m4J9-6cMje4-32" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-30" value="設計書取込" style="html=1;whiteSpace=wrap;strokeColor=#005700;fillColor=#008a00;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#ffffff;sketch=0;shape=mxgraph.sitemap.news;" parent="1" vertex="1">
|
||||
<mxGeometry x="440" y="715" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="Gi77RX5G2m4J9-6cMje4-21" target="Gi77RX5G2m4J9-6cMje4-30" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-32" value="取込結果表示" style="html=1;whiteSpace=wrap;strokeColor=#005700;fillColor=#008a00;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#ffffff;sketch=0;shape=mxgraph.sitemap.news;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="715" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-37" value="設計書ダウロード" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.news;" parent="1" vertex="1">
|
||||
<mxGeometry x="440" y="825" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="Gi77RX5G2m4J9-6cMje4-21" target="Gi77RX5G2m4J9-6cMje4-37" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-39" value="フロー履歴管理" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.news;" parent="1" vertex="1">
|
||||
<mxGeometry x="980" y="610" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-41" value="ALC設定" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="220" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-43" value="管理ドメイン設定" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="800" y="220" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="Gi77RX5G2m4J9-6cMje4-41" target="Gi77RX5G2m4J9-6cMje4-43" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-45" value="プロファイル" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="440" y="935" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="Gi77RX5G2m4J9-6cMje4-21" target="Gi77RX5G2m4J9-6cMje4-45" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-50" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Gi77RX5G2m4J9-6cMje4-47" target="Gi77RX5G2m4J9-6cMje4-49" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-47" value="プロファイル" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="440" y="450" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-48" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="Gi77RX5G2m4J9-6cMje4-5" target="Gi77RX5G2m4J9-6cMje4-47" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-49" value="ライセンス情報" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="450" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-51" value="ライセンス情報" style="html=1;whiteSpace=wrap;strokeColor=none;fillColor=#0079D6;labelPosition=center;verticalLabelPosition=middle;verticalAlign=top;align=center;fontSize=12;outlineConnect=0;spacingTop=-6;fontColor=#FFFFFF;sketch=0;shape=mxgraph.sitemap.home;" parent="1" vertex="1">
|
||||
<mxGeometry x="620" y="935" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="Gi77RX5G2m4J9-6cMje4-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="Gi77RX5G2m4J9-6cMje4-45" target="Gi77RX5G2m4J9-6cMje4-51" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,2 +1,3 @@
|
||||
KAB_BACKEND_URL="https://kab-backend.azurewebsites.net/"
|
||||
#KAB_BACKEND_URL="http://127.0.0.1:8000/"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "kintone-automate",
|
||||
"version": "0.2.0",
|
||||
"description": "Kintoneアプリの自動生成とデプロイを支援ツールです",
|
||||
"productName": "kintone Automate",
|
||||
"productName": "Kintone Automate",
|
||||
"author": "maxiaozhe@alicorns.co.jp <maxiaozhe@alicorns.co.jp>",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -36,8 +36,7 @@ module.exports = configure(function (/* ctx */) {
|
||||
// --> boot files are part of "main.js"
|
||||
// https://v2.quasar.dev/quasar-cli-vite/boot-files
|
||||
boot: [
|
||||
'axios',
|
||||
'error-handler'
|
||||
'axios'
|
||||
],
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
||||
|
||||
@@ -20,20 +20,22 @@ const token=localStorage.getItem('token')||'';
|
||||
if(token!==''){
|
||||
api.defaults.headers["Authorization"]='Bearer ' + token;
|
||||
}
|
||||
//axios例外キャプチャー
|
||||
api.interceptors.response.use(
|
||||
(response)=>response,
|
||||
(error)=>{
|
||||
if (error.response && error.response.status === 401) {
|
||||
// 認証エラーの場合再ログインする
|
||||
console.error('(; ゚Д゚)/認証エラー(401):', error);
|
||||
const orgReq=error.config;
|
||||
if(error.response && error.response.status===401){
|
||||
console.error("401エラー");
|
||||
localStorage.removeItem('token');
|
||||
router.replace({
|
||||
path:"/login",
|
||||
query:{redirect:router.currentRoute.value.fullPath}
|
||||
});
|
||||
// router.push({
|
||||
// path:"/login",
|
||||
// query:{redirect:router.currentRoute.value.fullPath}
|
||||
// });
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
)
|
||||
export default boot(({ app }) => {
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// src/boot/error-handler.ts
|
||||
import { boot } from 'quasar/wrappers';
|
||||
import { Router } from 'vue-router';
|
||||
import { App } from 'vue';
|
||||
|
||||
export default boot(({ app, router }: { app: App<Element>; router: Router }) => {
|
||||
app.config.errorHandler = (err: any, instance: any, info: string) => {
|
||||
if (err.response && err.response.status === 401) {
|
||||
// 認証エラーの場合再ログインする
|
||||
console.error('(; ゚Д゚)/認証エラー(401):', err, info);
|
||||
localStorage.removeItem('token');
|
||||
router.replace({
|
||||
path:"/login",
|
||||
query:{redirect:router.currentRoute.value.fullPath}
|
||||
});
|
||||
} else {
|
||||
console.error('(; ゚Д゚)例外:', err, info);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -3,15 +3,13 @@
|
||||
<div v-if="!isLoaded" class="spinner flex flex-center">
|
||||
<q-spinner color="primary" size="3em" />
|
||||
</div>
|
||||
<q-table v-else row-key="index" :selection="type" v-model:selected="selected" :columns="columns" :rows="rows"
|
||||
<q-table v-else row-key="name" :selection="type" v-model:selected="selected" :columns="columns" :rows="rows"
|
||||
class="action-table"
|
||||
flat bordered
|
||||
virtual-scroll
|
||||
:pagination="pagination"
|
||||
:rows-per-page-options="[0]"
|
||||
:filter="filter"
|
||||
>
|
||||
</q-table>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -22,10 +20,9 @@ export default {
|
||||
name: 'actionSelect',
|
||||
props: {
|
||||
name: String,
|
||||
type: String,
|
||||
filter:String
|
||||
type: String
|
||||
},
|
||||
setup(props) {
|
||||
setup() {
|
||||
const isLoaded=ref(false);
|
||||
const columns = [
|
||||
{ name: 'name', required: true,label: 'アクション名',align: 'left',field: 'name',sortable: true},
|
||||
@@ -35,9 +32,9 @@ export default {
|
||||
const rows = reactive([])
|
||||
onMounted(async () => {
|
||||
const res =await api.get('api/actions');
|
||||
res.data.forEach((item,index) =>
|
||||
res.data.forEach((item) =>
|
||||
{
|
||||
rows.push({index,name:item.name,desc:item.title,outputPoints:item.outputpoints,property:item.property});
|
||||
rows.push({name:item.name,desc:item.title,outputPoints:item.outputpoints,property:item.property});
|
||||
});
|
||||
isLoaded.value=true;
|
||||
});
|
||||
@@ -56,7 +53,6 @@ export default {
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.action-table{
|
||||
min-height: 10vh;
|
||||
max-height: 68vh;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,68 +1,56 @@
|
||||
<template>
|
||||
<div class="q-px-xs">
|
||||
<div class="q-pa-md" >
|
||||
<div v-if="!isLoaded" class="spinner flex flex-center">
|
||||
<q-spinner color="primary" size="3em" />
|
||||
<q-spinner color="primary" size="3em" />
|
||||
</div>
|
||||
<q-table v-else class="app-table" :selection="type" row-key="id" v-model:selected="selected" flat bordered
|
||||
virtual-scroll :columns="columns" :rows="rows" :pagination="pagination" :rows-per-page-options="[0]"
|
||||
:filter="filter" style="max-height: 65vh;">
|
||||
<q-table v-else :selection="type" v-model:selected="selected" :columns="columns" :rows="rows" >
|
||||
<template v-slot:body-cell-description="props">
|
||||
<q-td :props="props">
|
||||
<q-scroll-area class="description-cell">
|
||||
<div v-html="props.row.description"></div>
|
||||
</q-scroll-area>
|
||||
</q-td>
|
||||
<q-td :props="props">
|
||||
<q-scroll-area class="description-cell">
|
||||
<div v-html="props.row.description" ></div>
|
||||
</q-scroll-area>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref, onMounted, reactive, watchEffect } from 'vue'
|
||||
import { ref,onMounted,reactive } from 'vue'
|
||||
import { api } from 'boot/axios';
|
||||
import { LeftDataBus } from './flowEditor/left/DataBus';
|
||||
|
||||
export default {
|
||||
name: 'AppSelect',
|
||||
props: {
|
||||
name: String,
|
||||
type: String,
|
||||
filter: String,
|
||||
updateExternalSelectAppInfo: {
|
||||
type: Function
|
||||
}
|
||||
type: String
|
||||
},
|
||||
setup(props) {
|
||||
const columns = [
|
||||
{ name: 'id', required: true, label: 'ID', align: 'left', field: 'id', sortable: true },
|
||||
{ name: 'name', label: 'アプリ名', field: 'name', sortable: true, align: 'left' },
|
||||
{ name: 'description', label: '概要', field: 'description', align: 'left', sortable: false },
|
||||
{ name: 'createdate', label: '作成日時', field: 'createdate', align: 'left' }
|
||||
]
|
||||
const isLoaded = ref(false);
|
||||
const rows: any[] = reactive([]);
|
||||
const selected = ref([])
|
||||
|
||||
watchEffect(()=>{
|
||||
if (selected.value && selected.value[0] && props.updateExternalSelectAppInfo) {
|
||||
props.updateExternalSelectAppInfo(selected.value[0])
|
||||
}
|
||||
});
|
||||
onMounted(() => {
|
||||
api.get('api/v1/allapps').then(res => {
|
||||
res.data.apps.forEach((item: any) => {
|
||||
rows.push({
|
||||
id: item.appId,
|
||||
name: item.name,
|
||||
description: item.description,
|
||||
createdate: dateFormat(item.createdAt)
|
||||
});
|
||||
});
|
||||
isLoaded.value = true;
|
||||
setup() {
|
||||
const columns = [
|
||||
{ name: 'id', required: true,label: 'ID',align: 'left',field: 'id',sortable: true},
|
||||
{ name: 'name', label: 'アプリ名', field: 'name', sortable: true,align:'left' },
|
||||
{ name: 'description', label: '概要', field: 'description',align:'left', sortable: false },
|
||||
{ name: 'createdate', label: '作成日時', field: 'createdate',align:'left'}
|
||||
]
|
||||
const isLoaded=ref(false);
|
||||
const rows :any[]= reactive([]);
|
||||
onMounted( () => {
|
||||
api.get('api/v1/allapps').then(res =>{
|
||||
res.data.apps.forEach((item:any) =>
|
||||
{
|
||||
rows.push({
|
||||
id:item.appId,
|
||||
name:item.name,
|
||||
description:item.description,
|
||||
createdate:dateFormat(item.createdAt)});
|
||||
});
|
||||
isLoaded.value=true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const dateFormat = (dateStr: string) => {
|
||||
const dateFormat=(dateStr:string)=>{
|
||||
const date = new Date(dateStr);
|
||||
const pad = (num: number) => num.toString().padStart(2, '0');
|
||||
const pad = (num:number) => num.toString().padStart(2, '0');
|
||||
const year = date.getFullYear();
|
||||
const month = pad(date.getMonth() + 1);
|
||||
const day = pad(date.getDate());
|
||||
@@ -74,26 +62,22 @@ export default {
|
||||
return {
|
||||
columns,
|
||||
rows,
|
||||
selected,
|
||||
isLoaded,
|
||||
pagination: ref({
|
||||
rowsPerPage: 10
|
||||
})
|
||||
selected: ref([]),
|
||||
isLoaded
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.description-cell {
|
||||
.description-cell{
|
||||
height: 60px;
|
||||
width: 300px;
|
||||
max-height: 60px;
|
||||
max-width: 300px;
|
||||
white-space: break-spaces;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
.spinner{
|
||||
min-height: 300px;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
@@ -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" width="60vw" height="60vh">
|
||||
<template v-slot:toolbar>
|
||||
<q-btn flat round dense icon="more_vert" >
|
||||
<q-menu auto-close anchor="bottom start">
|
||||
|
||||
@@ -1,41 +1,30 @@
|
||||
<template>
|
||||
<q-field v-model="selectedObject" labelColor="primary" class="condition-object"
|
||||
<q-field v-model="selectedField" labelColor="primary" class="condition-object"
|
||||
:clearable="isSelected" stack-label :dense="true" :outlined="true" >
|
||||
<template v-slot:control >
|
||||
<q-chip color="primary" text-color="white" v-if="isSelected && selectedObject.objectType==='field'" :dense="true" class="selected-obj">
|
||||
{{ selectedObject.name }}
|
||||
</q-chip>
|
||||
<q-chip color="info" text-color="white" v-if="isSelected && selectedObject.objectType==='variable'" :dense="true" class="selected-obj">
|
||||
{{ selectedObject.name }}
|
||||
<q-chip color="primary" text-color="white" v-if="isSelected" :dense="true" class="selected-obj">
|
||||
{{ selectedField.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">
|
||||
<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>
|
||||
<condition-objects ref="appDg" name="フィールド" type="single" :filter="filter" :appId="store.appInfo?.appId" :vars="vars"></condition-objects>
|
||||
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeDg" widht="400px">
|
||||
<condition-objects ref="appDg" name="フィールド" type="single" :appId="store.appInfo?.appId"></condition-objects>
|
||||
</show-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, ref ,watchEffect,computed} from 'vue';
|
||||
import { defineComponent, ref ,watchEffect,computed} from 'vue';
|
||||
import ShowDialog from '../ShowDialog.vue';
|
||||
import ConditionObjects from '../ConditionObjects.vue';
|
||||
import { useFlowEditorStore } from '../../stores/flowEditor';
|
||||
import {IActionFlow,IActionNode,IActionVariable} from '../../types/ActionTypes';
|
||||
export default defineComponent({
|
||||
name: 'ConditionObject',
|
||||
components: {
|
||||
ShowDialog,
|
||||
ConditionObjects
|
||||
ConditionObjects,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
@@ -46,28 +35,24 @@
|
||||
setup(props, { emit }) {
|
||||
const appDg = ref();
|
||||
const show = ref(false);
|
||||
const selectedObject = ref(props.modelValue);
|
||||
const selectedField = ref(props.modelValue);
|
||||
const store = useFlowEditorStore();
|
||||
const isSelected = computed(()=>{
|
||||
return selectedObject.value!==null && typeof selectedObject.value === 'object' && ('name' in selectedObject.value)
|
||||
return selectedField.value!==null && typeof selectedField.value === 'object' && ('name' in selectedField.value)
|
||||
});
|
||||
let vars:IActionVariable[] =[];
|
||||
if(store.currentFlow!==undefined && store.activeNode!==undefined ){
|
||||
vars =store.currentFlow.getVarNames(store.activeNode);
|
||||
}
|
||||
const filter=ref('');
|
||||
|
||||
const showDg = () => {
|
||||
show.value = true;
|
||||
};
|
||||
|
||||
const closeDg = (val:string) => {
|
||||
if (val == 'OK') {
|
||||
selectedObject.value = appDg.value.selected[0];
|
||||
selectedField.value = appDg.value.selected[0];
|
||||
}
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
emit('update:modelValue', selectedObject.value);
|
||||
emit('update:modelValue', selectedField.value);
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -76,10 +61,8 @@
|
||||
show,
|
||||
showDg,
|
||||
closeDg,
|
||||
selectedObject,
|
||||
vars:reactive(vars),
|
||||
isSelected,
|
||||
filter
|
||||
selectedField,
|
||||
isSelected
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -106,7 +106,11 @@
|
||||
</div>
|
||||
</template>
|
||||
</q-tree>
|
||||
<q-tooltip anchor="center middle" v-model="showingCondition" no-parent-event>
|
||||
<!-- <q-btn @click="addCondition(tree.root)" class="q-mt-md" color="primary" icon="mdi-plus">Add Condition</q-btn> -->
|
||||
<!-- <q-btn @click="getConditionString()" class="q-mt-md" color="primary" icon="mdi-plus">Show Condtion</q-btn>
|
||||
<q-btn @click="getConditionJson()" class="q-mt-md" color="primary" icon="mdi-plus">Show Condtion data</q-btn>
|
||||
<q-btn @click="LoadCondition()" class="q-mt-md" color="primary" icon="mdi-plus">Load Condition</q-btn> -->
|
||||
<q-tooltip anchor="center middle" v-model="showingCondition" no-parent-event>
|
||||
import { finished } from 'stream';
|
||||
{{ conditionString }}
|
||||
</q-tooltip>
|
||||
|
||||
@@ -1,58 +1,53 @@
|
||||
<template>
|
||||
<div class="q-gutter-y-md" style="max-width: 600px;">
|
||||
<q-card >
|
||||
<q-tabs
|
||||
v-model="tab"
|
||||
dense
|
||||
class="text-grey"
|
||||
active-color="white"
|
||||
active-bg-color="primary"
|
||||
indicator-color="primary"
|
||||
align="justify"
|
||||
narrow-indicator
|
||||
>
|
||||
<q-tab name="fields" label="フィールド"></q-tab>
|
||||
<q-tab name="vars" label="変数"></q-tab>
|
||||
</q-tabs>
|
||||
|
||||
<q-separator></q-separator>
|
||||
|
||||
<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>
|
||||
</q-tab-panel>
|
||||
|
||||
<q-tab-panel name="vars" >
|
||||
<variable-list v-model="selected" type="single" :vars="vars"></variable-list>
|
||||
</q-tab-panel>
|
||||
</q-tab-panels>
|
||||
</q-card>
|
||||
</div>
|
||||
<div class="q-pa-md">
|
||||
<div v-if="!isLoaded" class="spinner flex flex-center">
|
||||
<q-spinner color="primary" size="3em" />
|
||||
</div>
|
||||
<q-table v-else row-key="name" :selection="type" v-model:selected="selected" :columns="columns" :rows="rows" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
import FieldList from './FieldList.vue';
|
||||
import VariableList from './VariableList.vue';
|
||||
<script>
|
||||
import { ref,onMounted,reactive } from 'vue'
|
||||
import { api } from 'boot/axios';
|
||||
|
||||
export default {
|
||||
name: 'ConditionObjects',
|
||||
components:{
|
||||
FieldList,
|
||||
VariableList
|
||||
},
|
||||
props: {
|
||||
name: String,
|
||||
type: String,
|
||||
appId: Number,
|
||||
vars: Array,
|
||||
filter:String
|
||||
appId:Number
|
||||
},
|
||||
setup(props) {
|
||||
const isLoaded=ref(false);
|
||||
const columns = [
|
||||
{ name: 'name', required: true,label: 'フィールド名',align: 'left',field: row=>row.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:fields[key].label,code:fields[key].code,type:fields[key].type});
|
||||
rows.push({name:fld.label,objectType:'field',...fld});
|
||||
});
|
||||
isLoaded.value=true;
|
||||
});
|
||||
|
||||
return {
|
||||
tab: ref('fields'),
|
||||
selected: ref([])
|
||||
}
|
||||
return {
|
||||
columns,
|
||||
rows,
|
||||
selected: ref([]),
|
||||
isLoaded
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ import { ref } from 'vue';
|
||||
const headers = ref([{name:"Authorization",value:'Bearer ' + authStore.token}]);
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
title:"設計書から導入する(csv or excel)",
|
||||
uploadUrl: `${process.env.KAB_BACKEND_URL}api/v1/createappfromexcel?format=1`
|
||||
uploadUrl: `${process.env.KAB_BACKEND_URL}api/v1/createappfromexcel`
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<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" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
import { api } from 'boot/axios';
|
||||
|
||||
export default {
|
||||
name: 'FieldList',
|
||||
props: {
|
||||
name: String,
|
||||
type: String,
|
||||
appId: Number,
|
||||
modelValue:Array,
|
||||
filter:String
|
||||
},
|
||||
emits:[
|
||||
'update:modelValue'
|
||||
],
|
||||
setup(props) {
|
||||
const isLoaded = ref(false);
|
||||
const columns = [
|
||||
{ name: 'name', required: true, label: 'フィールド名', align: 'left', field: row => row.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;
|
||||
});
|
||||
|
||||
return {
|
||||
columns,
|
||||
rows,
|
||||
// selected: ref([]),
|
||||
isLoaded
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
@@ -1,82 +1,53 @@
|
||||
<template>
|
||||
<div class="q-px-md" style=" min-width: 50vw; max-width: 85vw;">
|
||||
<div class="q-pa-md">
|
||||
<div v-if="!isLoaded" class="spinner flex flex-center">
|
||||
<q-spinner color="primary" size="3em" />
|
||||
<q-spinner color="primary" size="3em" />
|
||||
</div>
|
||||
<q-table flat bordered v-else row-key="name" :selection="type" v-model:selected="selected" :columns="columns"
|
||||
:rows="rows" :pagination="pageSetting" :filter="filter" style="max-height: 55vh;"/>
|
||||
<q-table v-else row-key="name" :selection="type" v-model:selected="selected" :columns="columns" :rows="rows" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { ref, onMounted, reactive, watchEffect } from 'vue'
|
||||
import { ref,onMounted,reactive } from 'vue'
|
||||
import { api } from 'boot/axios';
|
||||
|
||||
export default {
|
||||
name: 'fieldSelect',
|
||||
props: {
|
||||
name: String,
|
||||
type: {
|
||||
type: String,
|
||||
default: 'single'
|
||||
},
|
||||
appId: Number,
|
||||
not_page: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
selectedFields:{
|
||||
type:Array,
|
||||
default:()=>[]
|
||||
},
|
||||
updateSelects: {
|
||||
type: Function
|
||||
},
|
||||
filter: String,
|
||||
type: String,
|
||||
appId:Number
|
||||
},
|
||||
setup(props) {
|
||||
const isLoaded = ref(false);
|
||||
const isLoaded=ref(false);
|
||||
const columns = [
|
||||
{ name: 'name', required: true, label: 'フィールド名', align: 'left', field: row => row.name, sortable: true },
|
||||
{ name: 'code', label: 'フィールドコード', align: 'left', field: 'code', sortable: true },
|
||||
{ name: 'type', label: 'フィールドタイプ', align: 'left', field: 'type', sortable: true }
|
||||
{ name: 'name', required: true,label: 'フィールド名',align: 'left',field: row=>row.name,sortable: true},
|
||||
{ name: 'code', label: 'フィールドコード', align: 'left',field: 'code', sortable: true },
|
||||
{ name: 'type', label: 'フィールドタイプ', align: 'left',field: 'type', sortable: true }
|
||||
]
|
||||
const pageSetting = ref({
|
||||
sortBy: 'desc',
|
||||
descending: false,
|
||||
page: 2,
|
||||
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:[]);
|
||||
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:fields[key].label,code:fields[key].code,type:fields[key].type});
|
||||
rows.push({name:fld.label,...fld});
|
||||
});
|
||||
isLoaded.value=true;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
props.updateSelects(selected);
|
||||
});
|
||||
|
||||
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:fields[key].label,code:fields[key].code,type:fields[key].type});
|
||||
rows.push({ name: fld.label, ...fld });
|
||||
});
|
||||
isLoaded.value = true;
|
||||
});
|
||||
|
||||
return {
|
||||
columns,
|
||||
rows,
|
||||
selected,
|
||||
isLoaded,
|
||||
pageSetting
|
||||
}
|
||||
return {
|
||||
columns,
|
||||
rows,
|
||||
selected: ref([]),
|
||||
isLoaded
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@@ -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-dialog :model-value="visible" persistent bordered>
|
||||
<q-card :style="{minWidth : width}" >
|
||||
<q-toolbar class="bg-grey-4">
|
||||
<q-toolbar-title>{{ name }}</q-toolbar-title>
|
||||
<q-space></q-space>
|
||||
@@ -11,10 +11,10 @@
|
||||
<q-card-section>
|
||||
<!-- <div class="text-h6">{{ name }}</div> -->
|
||||
</q-card-section>
|
||||
<q-card-section class="q-pt-none" :style="sectionStyle">
|
||||
<q-card-section class="q-pt-none" :style="{...(height? {minHeight:height}:{}) }">
|
||||
<slot></slot>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right" class="text-primary q-mt-lg">
|
||||
<q-card-actions align="right" class="text-primary">
|
||||
<q-btn flat label="確定" v-close-popup @click="CloseDialogue('OK')" />
|
||||
<q-btn flat label="キャンセル" v-close-popup @click="CloseDialogue('Cancel')" />
|
||||
</q-card-actions>
|
||||
@@ -23,16 +23,14 @@
|
||||
<!-- </div> -->
|
||||
</template>
|
||||
<script>
|
||||
import {computed} from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'ShowDialog',
|
||||
props: {
|
||||
name:String,
|
||||
visible: Boolean,
|
||||
width:String,
|
||||
height:String,
|
||||
minWidth:String,
|
||||
minHeight:String
|
||||
height:String
|
||||
},
|
||||
emits: [
|
||||
'close'
|
||||
@@ -43,20 +41,8 @@ export default {
|
||||
context.emit('close', val);
|
||||
}
|
||||
|
||||
const cardStyle = computed(() => ({
|
||||
minWidth: props.minWidth,
|
||||
width: props.width
|
||||
}));
|
||||
|
||||
const sectionStyle = computed(() => ({
|
||||
height: props.height,
|
||||
minHeight: props.minHeight
|
||||
}));
|
||||
|
||||
return {
|
||||
CloseDialogue,
|
||||
cardStyle,
|
||||
sectionStyle
|
||||
CloseDialogue
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
<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" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref, reactive, PropType, compile } from 'vue';
|
||||
import {IActionNode,IActionVariable} from '../types/ActionTypes';
|
||||
|
||||
export default {
|
||||
name: 'VariableList',
|
||||
props: {
|
||||
name: String,
|
||||
type: String,
|
||||
vars:{
|
||||
type:Array as PropType<IActionVariable[]>,
|
||||
reqired:true,
|
||||
default:()=>[]
|
||||
},
|
||||
modelValue:Array
|
||||
},
|
||||
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 rows= props.vars.map((v)=>{
|
||||
return {objectType:'variable',...v};
|
||||
});
|
||||
|
||||
return {
|
||||
columns,
|
||||
rows:reactive(rows)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -22,15 +22,8 @@
|
||||
></q-btn>
|
||||
</div>
|
||||
</div>
|
||||
<ShowDialog v-model:visible="showSelectApp" name="アプリ選択" @close="closeDg" min-width="50vw" min-height="50vh" >
|
||||
<template v-slot:toolbar>
|
||||
<q-input dense debounce="300" v-model="filter" placeholder="検索" clearable>
|
||||
<template v-slot:before>
|
||||
<q-icon name="search" />
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
<AppSelect ref="appDg" name="アプリ" type="single" :filter="filter"></AppSelect>
|
||||
<ShowDialog v-model:visible="showSelectApp" name="アプリ選択" @close="closeDg" width="600px" >
|
||||
<AppSelect ref="appDg" name="アプリ" type="single"></AppSelect>
|
||||
</ShowDialog>
|
||||
</template>
|
||||
|
||||
@@ -80,8 +73,7 @@ export default defineComponent({
|
||||
showSelectApp,
|
||||
showAppDialog,
|
||||
closeDg,
|
||||
appDg,
|
||||
filter:ref('')
|
||||
appDg
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
<!-- <div class="q-pa-md q-gutter-sm"> -->
|
||||
<q-tree
|
||||
:nodes="store.eventTree.screens"
|
||||
node-key="eventId"
|
||||
node-key="label"
|
||||
children-key="events"
|
||||
no-connectors
|
||||
v-model:expanded="store.expandedScreen"
|
||||
:dense="true"
|
||||
:ref="tree"
|
||||
>
|
||||
<template v-slot:header-EVENT="prop">
|
||||
<template v-slot:default-header="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"
|
||||
@@ -17,78 +16,27 @@
|
||||
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">{{ 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>
|
||||
<!-- </div> -->
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, ref } from 'vue';
|
||||
import { IKintoneEvent ,IKintoneEventGroup, IKintoneEventNode, kintoneEvent} from '../../types/KintoneEvents';
|
||||
import { IKintoneEvent } from '../../types/KintoneEvents';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useFlowEditorStore } from 'stores/flowEditor';
|
||||
import { ActionFlow, ActionNode, RootAction } from 'src/types/ActionTypes';
|
||||
import ShowDialog from '../ShowDialog.vue';
|
||||
import FieldSelect from '../FieldSelect.vue';
|
||||
import { QTree } from 'quasar';
|
||||
export default defineComponent({
|
||||
name: 'EventTree',
|
||||
components: {
|
||||
ShowDialog,
|
||||
FieldSelect,
|
||||
},
|
||||
setup(props, context) {
|
||||
const appDg = ref();
|
||||
const store = useFlowEditorStore();
|
||||
const showDialog = ref(false);
|
||||
const tree = ref<QTree>();
|
||||
// const eventTree=ref(kintoneEvents);
|
||||
// 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 closeDg = (val:string) => {
|
||||
if (val == 'OK') {
|
||||
if(!selectedChangeEvent.value){return;}
|
||||
const field = appDg.value.selected[0];
|
||||
const eventid = `${selectedChangeEvent.value.eventId}.${field.code}`;
|
||||
if(store.eventTree.findEventById(eventid)){
|
||||
return;
|
||||
}
|
||||
selectedChangeEvent.value?.events.push(
|
||||
new kintoneEvent(
|
||||
field.label,
|
||||
eventid,
|
||||
selectedChangeEvent.value.eventId)
|
||||
);
|
||||
tree.value?.expanded?.push(selectedChangeEvent.value.eventId);
|
||||
tree.value?.expandAll();
|
||||
}
|
||||
};
|
||||
const addChangeEvent=(node:IKintoneEventGroup)=>{
|
||||
if(store.appInfo===undefined){
|
||||
return;
|
||||
}
|
||||
selectedChangeEvent.value=node;
|
||||
showDialog.value=true;
|
||||
}
|
||||
const onSelected=(node:IKintoneEvent)=>{
|
||||
if(!node.eventId){
|
||||
return;
|
||||
@@ -97,35 +45,24 @@ export default defineComponent({
|
||||
if(store.appInfo===undefined){
|
||||
return;
|
||||
}
|
||||
const screen = store.eventTree.findEventById(node.parentId);
|
||||
const screen = store.eventTree.findScreen(node.eventId);
|
||||
let flow =store.findFlowByEventId(node.eventId);
|
||||
let screenName=screen!==null?screen.label:"";
|
||||
let nodeLabel = node.label;
|
||||
// if(isFieldChange(node)){
|
||||
// screenName=nodeLabel;
|
||||
// nodeLabel=`${node.label}の値を変更したとき`;
|
||||
// }
|
||||
const screenName=screen!==null?screen.label:"";
|
||||
if(flow!==undefined && flow!==null ){
|
||||
store.selectFlow(flow);
|
||||
}else{
|
||||
const root = new RootAction(node.eventId,screenName,nodeLabel)
|
||||
const root = new RootAction(node.eventId,screenName,node.label)
|
||||
const flow =new ActionFlow(root);
|
||||
store.flows?.push(flow);
|
||||
store.selectFlow(flow);
|
||||
selectedEvent.value.flowData=flow;
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
// eventTree,
|
||||
// expanded,
|
||||
appDg,
|
||||
tree,
|
||||
showDialog,
|
||||
isFieldChange,
|
||||
onSelected,
|
||||
selectedEvent,
|
||||
addChangeEvent,
|
||||
closeDg,
|
||||
store
|
||||
}
|
||||
}
|
||||
@@ -146,6 +83,4 @@ export default defineComponent({
|
||||
.event-node:hover{
|
||||
background-color: $light-blue-1;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="row justify-center no-wrap" >
|
||||
<div class="row justify-center" :style="{ marginLeft: node.inputPoint !== '' ? '240px' : '' }" >
|
||||
<div class="row">
|
||||
<q-card class="action-node" :class="nodeStyle" :square="false" @click="onNodeClick" >
|
||||
<q-toolbar class="col" >
|
||||
@@ -8,10 +8,6 @@
|
||||
<q-btn flat round dense icon="more_horiz" size="sm" >
|
||||
<q-menu auto-close anchor="top right">
|
||||
<q-list>
|
||||
<q-item clickable v-if="isRoot" @click="copyFlow">
|
||||
<q-item-section avatar><q-icon name="content_copy" ></q-icon></q-item-section>
|
||||
<q-item-section >コピーする</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-if="!isRoot" @click="onEditNode">
|
||||
<q-item-section avatar><q-icon name="edit" ></q-icon></q-item-section>
|
||||
<q-item-section >編集する</q-item-section>
|
||||
@@ -29,7 +25,7 @@
|
||||
</q-btn>
|
||||
</q-toolbar>
|
||||
<q-separator />
|
||||
<q-card-section class="action-title">
|
||||
<q-card-section>
|
||||
<div class="row">
|
||||
<span class="text-h7">{{ node.title }}</span>
|
||||
<q-space></q-space>
|
||||
@@ -48,34 +44,23 @@
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="hasBranch">
|
||||
<node-line :action-node="node" @addNode="addNode" :left-columns="leftColumns" :right-columns="rightColumns"></node-line>
|
||||
<div class="row justify-center no-wrap" >
|
||||
<div v-for="(point, index) in node.outputPoints" :key="index" class="column" style="min-width: 300px;">
|
||||
<div class="justify-center" >
|
||||
<node-item v-if="nextNode(point)!==undefined" :key="nextNode(point).id" :isSelected="nextNode(point) === store.activeNode"
|
||||
:actionNode="nextNode(point)" @addNode="addNodeFromItem" @nodeSelected="onNodeSelected" @nodeEdit="onNodeEdit"
|
||||
@deleteNode="onDeleteNodeFromItem" @deleteAllNextNodes="onDeleteAllNextNodes" ></node-item>
|
||||
</div>
|
||||
<div class="row justify-center" :style="{ marginLeft: node.inputPoint !== '' ? '240px' : '' }">
|
||||
<div v-for="(point, index) in node.outputPoints" :key="index">
|
||||
<node-line :action-node="node" :mode="getMode(point)" @addNode="addNode" :input-point="point"></node-line>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="!hasBranch">
|
||||
<div class="row justify-center no-wrap" >
|
||||
<node-line :action-node="node" @addNode="addNode" ></node-line>
|
||||
</div>
|
||||
<div>
|
||||
<node-item v-if="nextNode('')!==undefined" :key="nextNode('').id" :isSelected="nextNode('') === store.activeNode"
|
||||
:actionNode="nextNode('')" @addNode="addNodeFromItem" @nodeSelected="onNodeSelected" @nodeEdit="onNodeEdit"
|
||||
@deleteNode="onDeleteNodeFromItem" @deleteAllNextNodes="onDeleteAllNextNodes" ></node-item>
|
||||
<div class="row justify-center" :style="{ marginLeft: node.inputPoint !== '' ? '240px' : '' }">
|
||||
<node-line :action-node="node" :mode="getMode('')" @addNode="addNode" input-point=""></node-line>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, ref } from 'vue';
|
||||
import { IActionNode, IActionProperty } from '../../types/ActionTypes';
|
||||
import { IActionNode } from '../../types/ActionTypes';
|
||||
import NodeLine, { Direction } from '../main/NodeLine.vue';
|
||||
import { useFlowEditorStore } from 'stores/flowEditor';
|
||||
export default defineComponent({
|
||||
name: 'NodeItem',
|
||||
components: {
|
||||
@@ -96,10 +81,8 @@ export default defineComponent({
|
||||
"nodeEdit",
|
||||
"deleteNode",
|
||||
"deleteAllNextNodes",
|
||||
"copyFlow"
|
||||
],
|
||||
setup(props, context) {
|
||||
const store = useFlowEditorStore();
|
||||
const hasBranch = computed(() => props.actionNode.outputPoints.length > 0);
|
||||
const nodeStyle = computed(() => {
|
||||
return {
|
||||
@@ -108,11 +91,23 @@ export default defineComponent({
|
||||
'selected': props.isSelected && !props.actionNode.isRoot
|
||||
};
|
||||
});
|
||||
|
||||
const nextNode=(point:string)=>{
|
||||
const nextId= props.actionNode.nextNodeIds.get(point);
|
||||
if(!nextId) return undefined;
|
||||
return store.currentFlow?.findNodeById(nextId);
|
||||
const getMode = (point: string) => {
|
||||
if (point === '' || props.actionNode.outputPoints.length === 0) {
|
||||
return Direction.Default;
|
||||
}
|
||||
if (point === props.actionNode.outputPoints[0]) {
|
||||
if (props.actionNode.nextNodeIds.get(point)) {
|
||||
return Direction.Left;
|
||||
} else {
|
||||
return Direction.LeftNotNext;
|
||||
}
|
||||
} else {
|
||||
if (props.actionNode.nextNodeIds.get(point)) {
|
||||
return Direction.Right;
|
||||
} else {
|
||||
return Direction.RightNotNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* アクションノード追加イベントを
|
||||
@@ -121,38 +116,6 @@ export default defineComponent({
|
||||
const addNode = (point: string) => {
|
||||
context.emit('addNode', props.actionNode, point);
|
||||
}
|
||||
/**
|
||||
* アクションノード追加イベントを
|
||||
* @param point 入力ポイント
|
||||
*/
|
||||
const addNodeFromItem = (node:IActionNode,point: string) => {
|
||||
context.emit('addNode', node, point);
|
||||
}
|
||||
|
||||
const leftColumns=computed(()=>{
|
||||
if(!props.actionNode.outputPoints || props.actionNode.outputPoints.length<2){
|
||||
return 1;
|
||||
}
|
||||
const leftNode = nextNode(props.actionNode.outputPoints[0]);
|
||||
if(leftNode){
|
||||
return store.currentFlow?.getColumns(leftNode);
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
const rightColumns=computed(()=>{
|
||||
if(!props.actionNode.outputPoints || props.actionNode.outputPoints.length<2){
|
||||
return 1;
|
||||
}
|
||||
const rightNode = nextNode(props.actionNode.outputPoints[1]);
|
||||
if(rightNode){
|
||||
return store.currentFlow?.getColumns(rightNode);
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* ノード選択状態
|
||||
*/
|
||||
@@ -160,20 +123,9 @@ export default defineComponent({
|
||||
context.emit('nodeSelected', props.actionNode);
|
||||
}
|
||||
|
||||
|
||||
const onNodeSelected = (node: IActionNode) => {
|
||||
context.emit('nodeSelected', node);
|
||||
}
|
||||
|
||||
const onEditNode=()=>{
|
||||
context.emit('nodeEdit', props.actionNode);
|
||||
}
|
||||
|
||||
const onNodeEdit=(node:IActionNode)=>{
|
||||
context.emit('nodeEdit', node);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ノードを削除する
|
||||
*/
|
||||
@@ -181,25 +133,12 @@ export default defineComponent({
|
||||
context.emit('deleteNode', props.actionNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* ノードを削除する
|
||||
*/
|
||||
const onDeleteNodeFromItem=(node:IActionNode)=>{
|
||||
context.emit('deleteNode', node);
|
||||
}
|
||||
/**
|
||||
* ノードの以下すべて削除する
|
||||
*/
|
||||
const onDeleteAllNode=()=>{
|
||||
context.emit('deleteAllNextNodes', props.actionNode);
|
||||
};
|
||||
|
||||
/**
|
||||
* ノードの以下すべて削除する
|
||||
*/
|
||||
const onDeleteAllNextNodes=(node:IActionNode)=>{
|
||||
context.emit('deleteAllNextNodes', node);
|
||||
};
|
||||
/**
|
||||
* 変数名取得
|
||||
*/
|
||||
@@ -207,42 +146,25 @@ export default defineComponent({
|
||||
const prop = node.actionProps.find((prop) => prop.props.name === "verName");
|
||||
return prop?.props.modelValue;
|
||||
};
|
||||
const copyFlow=()=>{
|
||||
context.emit('copyFlow', props.actionNode);
|
||||
}
|
||||
return {
|
||||
store,
|
||||
node: props.actionNode,
|
||||
nextNode,
|
||||
isRoot: props.actionNode.isRoot,
|
||||
hasBranch,
|
||||
nodeStyle,
|
||||
// getMode,
|
||||
getMode,
|
||||
addNode,
|
||||
addNodeFromItem,
|
||||
onNodeClick,
|
||||
onNodeSelected,
|
||||
onEditNode,
|
||||
onNodeEdit,
|
||||
onDeleteNode,
|
||||
onDeleteNodeFromItem,
|
||||
onDeleteAllNode,
|
||||
onDeleteAllNextNodes,
|
||||
copyFlow,
|
||||
varName,
|
||||
leftColumns,
|
||||
rightColumns
|
||||
varName
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.action-node {
|
||||
min-width: 280px !important;
|
||||
}
|
||||
.action-title{
|
||||
max-width: 280px !important;
|
||||
overflow-wrap: anywhere;
|
||||
min-width: 300px !important;
|
||||
}
|
||||
|
||||
.line {
|
||||
|
||||
@@ -1,28 +1,11 @@
|
||||
<template>
|
||||
<div class="row justify-center">
|
||||
<svg class="node-line" style="width:100%" :viewBox="viewBox()">
|
||||
<template v-if="!node.outputPoints || node.outputPoints.length===0" >
|
||||
<polyline :points="points(getMode('')).linePoints" class="line" ></polyline>
|
||||
<text class="add-icon"
|
||||
@click="addNode(node,'')"
|
||||
:x="points(getMode('')).iconPoint.x"
|
||||
:y="points(getMode('')).iconPoint.y"
|
||||
font-family="Arial" font-size="25"
|
||||
text-anchor="middle" dy=".3em" style="cursor: pointer;" >
|
||||
⊕
|
||||
</text>
|
||||
</template>
|
||||
<template v-for="(point, index) in node.outputPoints" :key="index" >
|
||||
<polyline :points="points(getMode(point)).linePoints" class="line" ></polyline>
|
||||
<text class="add-icon"
|
||||
@click="addNode(node,point)"
|
||||
:x="points(getMode(point)).iconPoint.x"
|
||||
:y="points(getMode(point)).iconPoint.y"
|
||||
font-family="Arial" font-size="25"
|
||||
text-anchor="middle" dy=".3em" style="cursor: pointer;" >
|
||||
⊕
|
||||
</text>
|
||||
</template>
|
||||
<div>
|
||||
<svg class="node-line">
|
||||
<polyline :points="points.linePoints" class="line" ></polyline>
|
||||
<text class="add-icon" @click="addNode(node)" :x="points.iconPoint.x" :y="points.iconPoint.y" font-family="Arial" font-size="25"
|
||||
text-anchor="middle" dy=".3em" style="cursor: pointer;" >
|
||||
⊕
|
||||
</text>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
@@ -44,97 +27,55 @@ export default defineComponent({
|
||||
type: Object as PropType<IActionNode>,
|
||||
required: true
|
||||
},
|
||||
leftColumns:{
|
||||
type:Number,
|
||||
required:false
|
||||
mode: {
|
||||
type: String as PropType<Direction>,
|
||||
required: true
|
||||
},
|
||||
rightColumns:{
|
||||
type:Number,
|
||||
required:false
|
||||
inputPoint:{
|
||||
type:String
|
||||
}
|
||||
},
|
||||
emits: ['addNode'],
|
||||
setup(props,context) {
|
||||
const hasBranch = computed(() => props.actionNode.outputPoints.length > 0);
|
||||
const getMode = (point: string):Direction => {
|
||||
if (point === '' || props.actionNode.outputPoints.length === 0) {
|
||||
return Direction.Default;
|
||||
}
|
||||
if (point === props.actionNode.outputPoints[0]) {
|
||||
if (props.actionNode.nextNodeIds.get(point)) {
|
||||
return Direction.Left;
|
||||
} else {
|
||||
return Direction.LeftNotNext;
|
||||
}
|
||||
} else {
|
||||
if (props.actionNode.nextNodeIds.get(point)) {
|
||||
return Direction.Right;
|
||||
} else {
|
||||
return Direction.RightNotNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const points = (mode:Direction) => {
|
||||
let startX ,endX;
|
||||
const leftColumn=props.leftColumns?props.leftColumns:1;
|
||||
const rightColumn=props.rightColumns?props.rightColumns:1;
|
||||
|
||||
switch (mode) {
|
||||
case Direction.Left:
|
||||
startX = leftColumn*300/2.0;
|
||||
endX = ((leftColumn+rightColumn)/2.0 - 0.25)*300;
|
||||
const points = computed(() => {
|
||||
switch (props.mode) {
|
||||
case Direction.Left:
|
||||
return {
|
||||
linePoints: `${startX}, 60, ${startX}, 40, ${endX}, 40, ${endX}, 0`,
|
||||
iconPoint: { x: endX, y: 20 }
|
||||
linePoints: '180, 0, 180, 40, 120, 40, 120, 60',
|
||||
iconPoint: { x: 180, y: 20 }
|
||||
};
|
||||
case Direction.Right:
|
||||
startX = ((leftColumn+rightColumn)/2.0 + 0.25)*300;
|
||||
endX = (leftColumn+(rightColumn/2.0))*300;
|
||||
return {
|
||||
linePoints: `${startX}, 0, ${startX}, 40, ${endX}, 40, ${endX}, 60`,
|
||||
iconPoint: { x: startX, y: 20 }
|
||||
linePoints: '60, 0, 60, 40, 120, 40, 120, 60',
|
||||
iconPoint: { x: 60, y: 20 }
|
||||
};
|
||||
case Direction.LeftNotNext:
|
||||
startX = ((leftColumn+rightColumn)/2.0 - 0.25)*300;
|
||||
return {
|
||||
linePoints: `${startX}, 0, ${startX}, 40`,
|
||||
iconPoint: { x: startX, y: 20 }
|
||||
linePoints: '180, 0, 180, 40',
|
||||
iconPoint: { x: 180, y: 20 }
|
||||
};
|
||||
case Direction.RightNotNext:
|
||||
startX = ((leftColumn+rightColumn)/2.0 + 0.25)*300;
|
||||
return {
|
||||
linePoints: `${startX}, 0, ${startX}, 40`,
|
||||
iconPoint: { x: startX, y: 20 }
|
||||
linePoints: '60, 0, 60, 40',
|
||||
iconPoint: { x: 60, y: 30 }
|
||||
};
|
||||
default:
|
||||
return {
|
||||
linePoints: '150, 0, 150, 60',
|
||||
iconPoint: { x: 150, y: 30 }
|
||||
linePoints: '120, 0, 120, 60',
|
||||
iconPoint: { x: 120, y: 30 }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const addNode=(prveNode:IActionNode,point:string)=>{
|
||||
context.emit('addNode',point);
|
||||
});
|
||||
const addNode=(prveNode:IActionNode)=>{
|
||||
context.emit('addNode',props.inputPoint);
|
||||
}
|
||||
|
||||
const viewBox=()=>{
|
||||
let columns=0;
|
||||
if(props.leftColumns!==undefined) columns+=props.leftColumns;
|
||||
if(props.rightColumns!==undefined) columns+=props.rightColumns;
|
||||
if(columns===0) columns=1;
|
||||
const width= columns*300;
|
||||
return `0 0 ${width} 60`;
|
||||
};
|
||||
|
||||
return {
|
||||
node: props.actionNode,
|
||||
getMode,
|
||||
hasBranch,
|
||||
points,
|
||||
addNode,
|
||||
viewBox
|
||||
addNode
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-for="(item, index) in componentData" :key="index">
|
||||
<component :is="item.component" v-bind="item.props" :connectProps="connectProps" v-model="item.props.modelValue"></component>
|
||||
<component :is="item.component" v-bind="item.props" v-model="item.props.modelValue"></component>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent,computed } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import InputText from '../right/InputText.vue';
|
||||
import SelectBox from '../right/SelectBox.vue';
|
||||
import DatePicker from '../right/DatePicker.vue';
|
||||
import FieldInput from '../right/FieldInput.vue';
|
||||
import EventSetter from '../right/EventSetter.vue';
|
||||
import { IActionProperty, IProp } from 'src/types/ActionTypes';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ActionProperty',
|
||||
components: {
|
||||
InputText,
|
||||
SelectBox,
|
||||
DatePicker,
|
||||
FieldInput,
|
||||
EventSetter
|
||||
FieldInput
|
||||
},
|
||||
props: {
|
||||
jsonData: {
|
||||
@@ -33,43 +31,27 @@ export default defineComponent({
|
||||
required: false,
|
||||
}
|
||||
},
|
||||
setup(props){
|
||||
const componentData=computed<Array<IActionProperty>>(()=>{
|
||||
return props.jsonData.elements.map((element: any) => {
|
||||
if(props.jsonValue != undefined )
|
||||
computed: {
|
||||
componentData() {
|
||||
return this.jsonData.elements.map((element: any) => {
|
||||
if(this.jsonValue != undefined )
|
||||
{
|
||||
if(props.jsonValue.hasOwnProperty(element.props.name))
|
||||
if(this.jsonValue.hasOwnProperty(element.props.name))
|
||||
{
|
||||
element.props.modelValue = props.jsonValue[element.props.name];
|
||||
element.props.modelValue = this.jsonValue[element.props.name];
|
||||
}
|
||||
else
|
||||
{
|
||||
element.props.modelValue = '';
|
||||
}
|
||||
|
||||
}
|
||||
return {
|
||||
component: element.component,
|
||||
props: element.props,
|
||||
};
|
||||
});
|
||||
});
|
||||
const connectProps=(props:IProp)=>{
|
||||
const connProps:any={};
|
||||
if(props && "connectProps" in props && props.connectProps!=undefined){
|
||||
for(let connProp of props.connectProps){
|
||||
let targetProp = componentData.value.find((prop)=>prop.props.name===connProp.propName);
|
||||
if(targetProp){
|
||||
connProps[connProp.key]=targetProp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return connProps;
|
||||
}
|
||||
|
||||
return{
|
||||
componentData,
|
||||
connectProps
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
<template>
|
||||
<div class="q-my-md" v-bind="$attrs">
|
||||
<q-card flat>
|
||||
<q-card-section class="q-pa-none q-my-sm q-mr-md">
|
||||
<!-- <div class=" q-my-none ">App Field Select</div> -->
|
||||
<div class="row q-mb-xs">
|
||||
<div class="text-primary q-mb-xs text-caption">{{ $props.displayName }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="q-mb-xs">{{ selectedField.app?.name || '未選択' }}</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<q-btn round flat size="sm" color="primary" icon="search" @click="showDg" />
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-separator />
|
||||
<q-card-section class="q-pa-none q-ma-none">
|
||||
<div style="">
|
||||
<div v-if="selectedField.fields && selectedField.fields.length > 0 ">
|
||||
<q-list bordered>
|
||||
<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-section>
|
||||
<q-item-section side>
|
||||
<q-btn round flat size="sm" icon="clear" @click="removeField(index)" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-virtual-scroll>
|
||||
</q-list>
|
||||
</div>
|
||||
<!-- <div v-else class="row q-mt-lg">
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- <q-separator /> -->
|
||||
</q-card-section>
|
||||
<q-card-section class="q-px-none q-py-xs" v-if="selectedField.fields && selectedField.fields.length===0">
|
||||
<div class="row">
|
||||
<div class="text-grey text-caption"> {{ $props.placeholder }}</div>
|
||||
<!-- <q-btn flat color="grey" label="clear" @click="clear" /> -->
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
|
||||
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeFieldDialog" ref="fieldDlg">
|
||||
|
||||
<div class="q-mx-md q-mb-lg">
|
||||
<div class="q-mb-xs q-ml-md text-primary">アプリ選択</div>
|
||||
|
||||
<div class="q-pa-md row" style="border: 1px solid rgba(0, 0, 0, 0.12); border-radius: 4px;">
|
||||
<div v-if="!showSelectApp && selectedField.app">{{ selectedField.app?.name }}</div>
|
||||
<q-space />
|
||||
<div>
|
||||
<q-btn outline dense label="選 択" padding="none sm" color="primary" @click="() => {
|
||||
showSelectApp = true;
|
||||
}"></q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!showSelectApp && selectedField.app?.name">
|
||||
<div>
|
||||
<div class="row q-mb-md">
|
||||
<!-- <div class="col"> -->
|
||||
<div class="q-mb-xs q-ml-md text-primary">フィールド選択</div>
|
||||
<!-- </div> -->
|
||||
<q-space />
|
||||
<!-- <div class="col"> -->
|
||||
<div class="q-mr-md">
|
||||
<q-input dense debounce="300" v-model="fieldFilter" placeholder="フィールド検索" clearable>
|
||||
<template v-slot:before>
|
||||
<q-icon name="search" />
|
||||
</template>
|
||||
</q-input>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="min-width: 45vw;" v-else>
|
||||
</div>
|
||||
|
||||
</show-dialog>
|
||||
|
||||
<show-dialog v-model:visible="showSelectApp" name="アプリ選択" @close="closeAppDlg">
|
||||
<template v-slot:toolbar>
|
||||
<q-input dense debounce="300" v-model="filter" placeholder="検索" clearable>
|
||||
<template v-slot:before>
|
||||
<q-icon name="search" />
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
|
||||
<AppSelect ref="appDlg" name="アプリ" type="single" :filter="filter"
|
||||
:updateExternalSelectAppInfo="updateExternalSelectAppInfo"></AppSelect>
|
||||
</show-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, watchEffect, computed } from 'vue';
|
||||
import ShowDialog from '../ShowDialog.vue';
|
||||
import FieldSelect from '../FieldSelect.vue';
|
||||
import { useFlowEditorStore } from 'stores/flowEditor';
|
||||
import AppSelect from '../AppSelect.vue';
|
||||
interface IApp{
|
||||
id:string,
|
||||
name:string
|
||||
}
|
||||
interface IField {
|
||||
name: string,
|
||||
code: string,
|
||||
type: string
|
||||
}
|
||||
|
||||
interface IAppFields{
|
||||
app?:IApp,
|
||||
fields:IField[]
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
inheritAttrs:false,
|
||||
name: 'FieldInput',
|
||||
components: {
|
||||
ShowDialog,
|
||||
FieldSelect,
|
||||
AppSelect,
|
||||
},
|
||||
props: {
|
||||
displayName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
selectType:{
|
||||
type:String,
|
||||
default:'single'
|
||||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const appDlg = ref();
|
||||
const fieldDlg = ref();
|
||||
const show = ref(false);
|
||||
const showSelectApp = ref(false);
|
||||
const selectedField = ref<IAppFields>({
|
||||
app:undefined,
|
||||
fields:[]
|
||||
});
|
||||
if(props.modelValue && "app" in props.modelValue && "fields" in props.modelValue){
|
||||
selectedField.value=props.modelValue as IAppFields;
|
||||
}
|
||||
const store = useFlowEditorStore();
|
||||
|
||||
const isSelected = computed(() => {
|
||||
return selectedField.value !== null && typeof selectedField.value === 'object' && ('app' in selectedField.value)
|
||||
});
|
||||
|
||||
const showDg = () => {
|
||||
show.value = true;
|
||||
};
|
||||
|
||||
const clear = () => {
|
||||
selectedField.value ={
|
||||
fields:[]
|
||||
} ;
|
||||
}
|
||||
|
||||
const closeAppDlg = (val: string) => {
|
||||
if (val == 'OK') {
|
||||
selectedField.value.app = appDlg.value.selected[0];
|
||||
selectedField.value.fields=[];
|
||||
showSelectApp.value=false;
|
||||
}
|
||||
};
|
||||
|
||||
const closeFieldDialog=(val:string)=>{
|
||||
if (val == 'OK') {
|
||||
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);
|
||||
}
|
||||
watchEffect(() => {
|
||||
emit('update:modelValue', selectedField.value);
|
||||
});
|
||||
|
||||
return {
|
||||
store,
|
||||
appDlg,
|
||||
fieldDlg,
|
||||
show,
|
||||
showDg,
|
||||
closeAppDlg,
|
||||
closeFieldDialog,
|
||||
selectedField,
|
||||
showSelectApp,
|
||||
isSelected,
|
||||
updateExternalSelectAppInfo,
|
||||
filter: ref(),
|
||||
updateItems,
|
||||
clear,
|
||||
fieldFilter: ref(),
|
||||
removeField
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,74 +0,0 @@
|
||||
<template>
|
||||
<div class="" v-bind="$attrs">
|
||||
<q-field v-model="color" :label="displayName" labelColor="primary" :clearable="isSelected" stack-label :bottom-slots="!isSelected" >
|
||||
<template v-slot:control>
|
||||
<q-chip text-color="black" color="white" v-if="isSelected">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<q-avatar class="shadow-1" :style="{ background: color }" size="xs"></q-avatar>
|
||||
</div>
|
||||
<div class="col">
|
||||
{{ color }}
|
||||
</div>
|
||||
</div>
|
||||
</q-chip>
|
||||
</template>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer" color="primary" >
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color no-header default-view="palette" v-model="color" />
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
<template v-slot:hint>
|
||||
{{ placeholder }}
|
||||
</template>
|
||||
</q-field>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, ref,watchEffect } from 'vue';
|
||||
export default defineComponent({
|
||||
inheritAttrs:false,
|
||||
name: 'ColorPicker',
|
||||
components: {
|
||||
},
|
||||
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 color = ref(props.modelValue??"");
|
||||
const isSelected = computed(()=>props.modelValue && props.modelValue!=="");
|
||||
watchEffect(()=>{
|
||||
emit('update:modelValue', color.value);
|
||||
});
|
||||
return {
|
||||
color,
|
||||
isSelected
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,20 +1,18 @@
|
||||
<template>
|
||||
<div v-bind="$attrs">
|
||||
<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-card-actions>
|
||||
<q-card-section class="text-caption" >
|
||||
<div v-if="!isSetted">{{ placeholder }}</div>
|
||||
<div v-else>{{ conditionString }}</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
</q-field>
|
||||
<condition-editor v-model:show="show" v-model:conditionTree="tree" @closed="onClosed"></condition-editor>
|
||||
</div>
|
||||
<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-card-actions>
|
||||
<q-card-section class="text-caption" >
|
||||
<div v-if="!isSetted">{{ placeholder }}</div>
|
||||
<div v-else>{{ conditionString }}</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
</q-field>
|
||||
<condition-editor v-model:show="show" v-model:conditionTree="tree" @closed="onClosed"></condition-editor>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -23,7 +21,6 @@
|
||||
import ConditionEditor from '../ConditionEditor/ConditionEditor.vue'
|
||||
export default defineComponent({
|
||||
name: 'FieldInput',
|
||||
inheritAttrs:false,
|
||||
components: {
|
||||
ConditionEditor
|
||||
},
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
<template>
|
||||
<div v-bind="$attrs">
|
||||
<q-input v-model="selectedDate" :label="displayName" :placeholder="placeholder" label-color="primary" mask="date" :rules="['date']" stack-label>
|
||||
<template v-slot:append>
|
||||
<q-icon name="event" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-date v-model="selectedDate">
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="Close" color="primary" flat />
|
||||
</div>
|
||||
</q-date>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
|
||||
<q-input v-model="selectedDate" :label="displayName" :placeholder="placeholder" label-color="primary" mask="date" :rules="['date']" stack-label>
|
||||
<template v-slot:append>
|
||||
<q-icon name="event" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-date v-model="selectedDate">
|
||||
<div class="row items-center justify-end">
|
||||
<q-btn v-close-popup label="Close" color="primary" flat />
|
||||
</div>
|
||||
</q-date>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -21,7 +20,6 @@ import { defineComponent, ref ,watchEffect} from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DatePicker',
|
||||
inheritAttrs:false,
|
||||
props: {
|
||||
displayName:{
|
||||
type: String,
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
<template>
|
||||
<div v-bind="$attrs">
|
||||
<q-input :label="displayName" v-model="inputValue" label-color="primary" :placeholder="placeholder" stack-label>
|
||||
<template v-slot:append>
|
||||
<q-btn round dense flat icon="add" @click="addButtonEvent()" />
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent,ref,watchEffect } from 'vue';
|
||||
import { useFlowEditorStore } from '../../stores/flowEditor';
|
||||
import { IKintoneEventGroup,kintoneEvent } from 'src/types/KintoneEvents';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'EventSetter',
|
||||
inheritAttrs:false,
|
||||
props: {
|
||||
displayName:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hint:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
connectProps:{
|
||||
type:Object,
|
||||
default:undefined
|
||||
}
|
||||
},
|
||||
|
||||
setup(props , { emit }) {
|
||||
const inputValue = ref(props.modelValue);
|
||||
const store = useFlowEditorStore();
|
||||
const addButtonEvent=()=>{
|
||||
const eventId =store.currentFlow?.getRoot()?.name;
|
||||
if(eventId===undefined){return;}
|
||||
let displayName = inputValue.value;
|
||||
if(props.connectProps!==undefined && "displayName" in props.connectProps){
|
||||
displayName =props.connectProps["displayName"].props.modelValue;
|
||||
}
|
||||
const customButtonId=`${eventId}.customButtonClick`;
|
||||
const findedEvent = store.eventTree.findEventById(customButtonId);
|
||||
if(findedEvent && "events" in findedEvent){
|
||||
const customEvents = findedEvent as IKintoneEventGroup;
|
||||
const addEventId = customButtonId+"." + inputValue.value;
|
||||
if(store.eventTree.findEventById(addEventId)){
|
||||
return;
|
||||
}
|
||||
customEvents.events.push(
|
||||
new kintoneEvent(
|
||||
displayName,
|
||||
addEventId,
|
||||
customButtonId)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
emit('update:modelValue', inputValue.value);
|
||||
});
|
||||
|
||||
return {
|
||||
inputValue,
|
||||
addButtonEvent
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -1,52 +1,49 @@
|
||||
<template>
|
||||
<div v-bind="$attrs">
|
||||
<q-field v-model="selectedField" :label="displayName" labelColor="primary" :clearable="isSelected" stack-label
|
||||
:bottom-slots="!isSelected">
|
||||
<template v-slot:control>
|
||||
<q-chip color="primary" text-color="white" v-if="isSelected">
|
||||
{{ 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>
|
||||
<q-field v-model="selectedField" :label="displayName" labelColor="primary"
|
||||
:clearable="isSelected" stack-label :bottom-slots="!isSelected" >
|
||||
<template v-slot:control >
|
||||
<q-chip color="primary" text-color="white" v-if="isSelected">
|
||||
{{ 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>
|
||||
|
||||
<template v-slot:append>
|
||||
<q-icon name="search" class="cursor-pointer" color="primary" @click="showDg" />
|
||||
</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>
|
||||
</show-dialog>
|
||||
</div>
|
||||
<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" widht="400px">
|
||||
<field-select ref="appDg" name="フィールド" type="single" :appId="store.appInfo?.appId"></field-select>
|
||||
</show-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, watchEffect, computed } from 'vue';
|
||||
import { defineComponent, ref ,watchEffect,computed} from 'vue';
|
||||
import ShowDialog from '../ShowDialog.vue';
|
||||
import FieldSelect from '../FieldSelect.vue';
|
||||
import { useFlowEditorStore } from 'stores/flowEditor';
|
||||
interface IField {
|
||||
name: string,
|
||||
code: string,
|
||||
type: string
|
||||
interface IField{
|
||||
name:string,
|
||||
code:string,
|
||||
type:string
|
||||
}
|
||||
export default defineComponent({
|
||||
name: 'FieldInput',
|
||||
inheritAttrs:false,
|
||||
components: {
|
||||
ShowDialog,
|
||||
FieldSelect,
|
||||
},
|
||||
props: {
|
||||
displayName: {
|
||||
displayName:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
name:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
@@ -54,7 +51,7 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hint: {
|
||||
hint:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
@@ -69,15 +66,15 @@ export default defineComponent({
|
||||
const show = ref(false);
|
||||
const selectedField = ref(props.modelValue);
|
||||
const store = useFlowEditorStore();
|
||||
const isSelected = computed(() => {
|
||||
return selectedField.value !== null && typeof selectedField.value === 'object' && ('name' in selectedField.value)
|
||||
const isSelected = computed(()=>{
|
||||
return selectedField.value!==null && typeof selectedField.value === 'object' && ('name' in selectedField.value)
|
||||
});
|
||||
|
||||
const showDg = () => {
|
||||
show.value = true;
|
||||
};
|
||||
|
||||
const closeDg = (val: string) => {
|
||||
const closeDg = (val:string) => {
|
||||
if (val == 'OK') {
|
||||
selectedField.value = appDg.value.selected[0];
|
||||
}
|
||||
|
||||
@@ -1,34 +1,18 @@
|
||||
<template>
|
||||
<div v-bind="$attrs">
|
||||
<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">
|
||||
<div class="hint-text" v-html="hint" />
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
<q-input :label="displayName" v-model="inputValue" label-color="primary" :placeholder="placeholder" stack-label/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { kMaxLength } from 'buffer';
|
||||
import { defineComponent, ref, watchEffect } from 'vue';
|
||||
import { defineComponent,ref,watchEffect } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'InputText',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
displayName: {
|
||||
displayName:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
name:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
@@ -36,44 +20,26 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hint: {
|
||||
hint:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
maxLength:{
|
||||
type: Number,
|
||||
default:undefined
|
||||
},
|
||||
//例:[val=>!!val ||'入力してください']
|
||||
rules:{
|
||||
type:String,
|
||||
default:undefined
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
setup(props, { emit }) {
|
||||
setup(props , { emit }) {
|
||||
const inputValue = ref(props.modelValue);
|
||||
const rulesExp = props.rules===undefined?null : eval(props.rules);
|
||||
|
||||
watchEffect(() => {
|
||||
emit('update:modelValue', inputValue.value);
|
||||
});
|
||||
|
||||
return {
|
||||
inputValue,
|
||||
showhint: ref(false),
|
||||
rulesExp
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.hint-text {
|
||||
white-space: always;
|
||||
max-width: 450px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
<template>
|
||||
<div v-bind="$attrs">
|
||||
<q-input :label="displayName" label-color="primary" v-model="inputValue" :placeholder="placeholder" autogrow
|
||||
stack-label />
|
||||
</div>
|
||||
<q-input :label="displayName" label-color="primary" v-model="inputValue" :placeholder="placeholder" autogrow stack-label/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, watchEffect } from 'vue';
|
||||
import { defineComponent,ref,watchEffect } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MuiltInputText',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
displayName: {
|
||||
displayName:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
name:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
@@ -24,7 +20,7 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hint: {
|
||||
hint:{
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
<template>
|
||||
<div class="" v-bind="$attrs">
|
||||
<q-input v-model.number="numValue" type="number" :label="displayName" label-color="primary" stack-label bottom-slots
|
||||
:min="min"
|
||||
:max="max"
|
||||
:rules="rulesExp"
|
||||
>
|
||||
<template v-slot:hint>
|
||||
{{ placeholder }}
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, ref, watchEffect } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'NumInput',
|
||||
inheritAttrs:false,
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
displayName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hint: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
min:{
|
||||
type:Number,
|
||||
default:undefined
|
||||
},
|
||||
max:{
|
||||
type:Number,
|
||||
default:undefined
|
||||
},
|
||||
//[val=>!!val ||'数値を入力してください',val=>val<=100 && val>=1 || '1-100の範囲内の数値を入力してください']
|
||||
rules:{
|
||||
type:String,
|
||||
default:undefined
|
||||
},
|
||||
modelValue: {
|
||||
type: [Number , String],
|
||||
default: undefined
|
||||
},
|
||||
},
|
||||
|
||||
setup(props, { emit }) {
|
||||
const numValue = ref(props.modelValue);
|
||||
const rulesExp = props.rules===undefined?null : eval(props.rules);
|
||||
const isError = computed(()=>{
|
||||
const val = numValue.value;
|
||||
if (val === undefined) {
|
||||
return false;
|
||||
}
|
||||
const numVal = typeof val === "string" ? parseInt(val) : val;
|
||||
// Ensure parsed value is a valid number
|
||||
if (isNaN(numVal)) {
|
||||
return true;
|
||||
}
|
||||
// Check against min and max boundaries, if defined
|
||||
if ((props.min !== undefined && numVal < props.min) || (props.max !== undefined && numVal > props.max)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
watchEffect(()=>{
|
||||
emit("update:modelValue",numValue.value);
|
||||
});
|
||||
return {
|
||||
numValue,
|
||||
rulesExp
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -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" v-model="item.props.modelValue"></component>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -15,13 +15,9 @@ import InputText from '../right/InputText.vue';
|
||||
import SelectBox from '../right/SelectBox.vue';
|
||||
import DatePicker from '../right/DatePicker.vue';
|
||||
import FieldInput from '../right/FieldInput.vue';
|
||||
import AppFieldSelect from './AppFieldSelect.vue';
|
||||
import MuiltInputText from '../right/MuiltInputText.vue';
|
||||
import ConditionInput from '../right/ConditionInput.vue';
|
||||
import EventSetter from '../right/EventSetter.vue';
|
||||
import ColorPicker from './ColorPicker.vue';
|
||||
import NumInput from './NumInput.vue';
|
||||
import { IActionNode,IActionProperty,IProp } from 'src/types/ActionTypes';
|
||||
import { IActionNode,IActionProperty } from 'src/types/ActionTypes';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PropertyList',
|
||||
@@ -30,12 +26,8 @@ export default defineComponent({
|
||||
SelectBox,
|
||||
DatePicker,
|
||||
FieldInput,
|
||||
AppFieldSelect,
|
||||
MuiltInputText,
|
||||
ConditionInput,
|
||||
EventSetter,
|
||||
ColorPicker,
|
||||
NumInput
|
||||
ConditionInput
|
||||
},
|
||||
props: {
|
||||
nodeProps: {
|
||||
@@ -48,22 +40,9 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
setup(props, context) {
|
||||
const properties=ref(props.nodeProps);
|
||||
const connectProps=(props:IProp)=>{
|
||||
const connProps:any={};
|
||||
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);
|
||||
if(targetProp){
|
||||
connProps[connProp.key]=targetProp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return connProps;
|
||||
}
|
||||
const properties=ref(props.nodeProps)
|
||||
return {
|
||||
properties,
|
||||
connectProps
|
||||
properties
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
elevated
|
||||
overlay
|
||||
>
|
||||
<q-card class="column" style="max-width: 300px;min-height: 100%">
|
||||
<q-card class="column full-height" style="width: 300px">
|
||||
<q-card-section>
|
||||
<div class="text-h6">{{ actionNode?.subTitle }}:設定</div>
|
||||
<div class="text-h6">{{ actionNode.subTitle }}:設定</div>
|
||||
</q-card-section>
|
||||
<q-card-section class="col q-pt-none">
|
||||
<property-list :node-props="actionProps" v-if="showPanel" ></property-list>
|
||||
@@ -51,10 +51,10 @@ import { IActionNode } from 'src/types/ActionTypes';
|
||||
],
|
||||
setup(props,{emit}) {
|
||||
const showPanel =ref(props.drawerRight);
|
||||
const actionProps =ref(props.actionNode?.actionProps);
|
||||
const actionProps =ref(props.actionNode.actionProps);
|
||||
watchEffect(() => {
|
||||
showPanel.value = props.drawerRight;
|
||||
actionProps.value= props.actionNode?.actionProps;
|
||||
actionProps.value= props.actionNode.actionProps;
|
||||
});
|
||||
|
||||
const cancel = async() =>{
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<div v-bind="$attrs">
|
||||
<q-select v-model="selectedValue" :label="displayName" :options="options"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -9,7 +7,6 @@ import { defineComponent,ref,watchEffect } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SelectBox',
|
||||
inheritAttrs:false,
|
||||
props: {
|
||||
displayName:{
|
||||
type: String,
|
||||
|
||||
@@ -1,25 +1 @@
|
||||
// app global css in SCSS form
|
||||
::-webkit-scrollbar {
|
||||
height: 12px;
|
||||
width: 14px;
|
||||
background: transparent;
|
||||
z-index: 12;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
width: 10px;
|
||||
background-color: #c1c1c1;
|
||||
border-radius: 10px;
|
||||
z-index: 12;
|
||||
border: 4px solid rgba(0, 0, 0, 0);
|
||||
background-clip: padding-box;
|
||||
transition: background-color .32s ease-in-out;
|
||||
margin: 4px;
|
||||
min-height: 32px;
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #c1c1c1;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</q-header>
|
||||
|
||||
<q-drawer
|
||||
:model-value="authStore.toggleLeftDrawer"
|
||||
v-model="leftDrawerOpen"
|
||||
:show-if-above="false"
|
||||
bordered
|
||||
>
|
||||
@@ -151,10 +151,11 @@ const essentialLinks: EssentialLinkProps[] = [
|
||||
}
|
||||
];
|
||||
|
||||
const leftDrawerOpen = ref(false)
|
||||
const version = process.env.version;
|
||||
const productName = process.env.productName;
|
||||
|
||||
function toggleLeftDrawer() {
|
||||
authStore.toggleLeftMenu();
|
||||
leftDrawerOpen.value = !leftDrawerOpen.value
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,274 +1,246 @@
|
||||
<template>
|
||||
<q-page>
|
||||
<q-layout container class="absolute-full shadow-2 rounded-borders">
|
||||
<q-layout
|
||||
container
|
||||
class="absolute-full shadow-2 rounded-borders"
|
||||
>
|
||||
<div class="q-pa-sm q-gutter-sm ">
|
||||
<q-drawer side="left" :overlay="true" bordered v-model="drawerLeft" :show-if-above="false" elevated>
|
||||
<div class="flex-center fixed-top app-selector">
|
||||
<AppSelector />
|
||||
</div>
|
||||
<q-drawer
|
||||
side="left"
|
||||
:overlay="true"
|
||||
bordered
|
||||
v-model="drawerLeft"
|
||||
:show-if-above="false"
|
||||
elevated
|
||||
>
|
||||
<div class="flex-center fixed-top app-selector" >
|
||||
<AppSelector />
|
||||
</div>
|
||||
|
||||
<div class="flex-center absolute-full" style="padding-top:65px;padding-left:15px;padding-right:15px;">
|
||||
<q-scroll-area class="fit" :horizontal-thumb-style="{ opacity: '0' }">
|
||||
<EventTree />
|
||||
</q-scroll-area>
|
||||
</div>
|
||||
<div class="flex-center absolute-full" style="padding-top:65px;padding-left:15px;padding-right:15px;">
|
||||
<q-scroll-area class="fit" :horizontal-thumb-style="{ opacity: '0' }">
|
||||
<EventTree />
|
||||
</q-scroll-area>
|
||||
</div>
|
||||
|
||||
<div class="flex-center fixed-bottom bg-grey-3 q-pa-md row ">
|
||||
<q-btn color="secondary" glossy label="デプロイ" @click="onDeploy" icon="sync" :loading="deployLoading" />
|
||||
<q-space></q-space>
|
||||
<q-btn color="primary" label="保存" @click="onSaveFlow" icon="save" :loading="saveLoading" />
|
||||
</div>
|
||||
<div class="flex-center fixed-bottom bg-grey-3 q-pa-md row ">
|
||||
<q-btn color="secondary" glossy label="デプロイ" @click="onDeploy" icon="sync" :loading="deployLoading" />
|
||||
<q-space></q-space>
|
||||
<q-btn color="primary" label="保存" @click="onSaveFlow" icon="save" :loading="saveLoading"/>
|
||||
</div>
|
||||
</q-drawer>
|
||||
</div>
|
||||
<q-btn flat dense round
|
||||
:icon="drawerLeft?'keyboard_double_arrow_left':'keyboard_double_arrow_right'"
|
||||
:style="[drawerLeft?{'left':'300px'}:{'left':'0px'}]"
|
||||
@click="drawerLeft=!drawerLeft" class="expand" />
|
||||
<div class="q-pa-md q-gutter-sm" :style="{minWidth: minPanelWidth}">
|
||||
<div class="flowchart" v-if="store.currentFlow" :style="[drawerLeft?{paddingLeft:'300px'}:{}]">
|
||||
<node-item v-if="rootNode!==undefined" :key="rootNode.id" :isSelected="rootNode === store.activeNode"
|
||||
:actionNode="rootNode" @addNode="addNode" @nodeSelected="onNodeSelected" @nodeEdit="onNodeEdit"
|
||||
@deleteNode="onDeleteNode" @deleteAllNextNodes="onDeleteAllNextNodes" @copyFlow="onCopyFlow"></node-item>
|
||||
<div class="q-pa-md q-gutter-sm">
|
||||
<div class="flowchart" v-if="store.currentFlow">
|
||||
<node-item v-for="(node,) in store.currentFlow.actionNodes" :key="node.id"
|
||||
:isSelected="node===state.activeNode" :actionNode="node"
|
||||
@addNode="addNode"
|
||||
@nodeSelected="onNodeSelected"
|
||||
@nodeEdit="onNodeEdit"
|
||||
@deleteNode="onDeleteNode"
|
||||
@deleteAllNextNodes="onDeleteAllNextNodes"
|
||||
></node-item>
|
||||
</div>
|
||||
</div>
|
||||
<PropertyPanel :actionNode="store.activeNode" v-model:drawerRight="drawerRight"></PropertyPanel>
|
||||
<PropertyPanel :actionNode="state.activeNode" v-model:drawerRight="drawerRight"></PropertyPanel>
|
||||
</q-layout>
|
||||
<ShowDialog v-model:visible="showAddAction" name="アクション" @close="closeDg" min-width="500px" min-height="500px">
|
||||
<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>
|
||||
<action-select ref="appDg" name="model" :filter="filter" type="single"></action-select>
|
||||
<ShowDialog v-model:visible="showAddAction" name="アクション" @close="closeDg" width="350px">
|
||||
<action-select ref="appDg" name="model" type="single"></action-select>
|
||||
</ShowDialog>
|
||||
|
||||
</q-page>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { IActionNode, ActionNode, IActionFlow, ActionFlow, RootAction, IActionProperty } from 'src/types/ActionTypes';
|
||||
import {ref,reactive,computed,onMounted} from 'vue';
|
||||
import {IActionNode, ActionNode, IActionFlow, ActionFlow,RootAction, IActionProperty } from 'src/types/ActionTypes';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useFlowEditorStore } from 'stores/flowEditor';
|
||||
import { useAuthStore } from 'stores/useAuthStore';
|
||||
|
||||
import NodeItem from 'src/components/main/NodeItem.vue';
|
||||
import ShowDialog from 'components/ShowDialog.vue';
|
||||
import ActionSelect from 'components/ActionSelect.vue';
|
||||
import PropertyPanel from 'components/right/PropertyPanel.vue';
|
||||
import AppSelector from 'components/left/AppSelector.vue';
|
||||
import EventTree from 'components/left/EventTree.vue';
|
||||
import { FlowCtrl } from '../control/flowctrl';
|
||||
import {FlowCtrl } from '../control/flowctrl';
|
||||
import { useQuasar } from 'quasar';
|
||||
const deployLoading = ref(false);
|
||||
const saveLoading = ref(false);
|
||||
const drawerLeft = ref(false);
|
||||
const $q = useQuasar();
|
||||
const store = useFlowEditorStore();
|
||||
const authStore = useAuthStore();
|
||||
|
||||
const drawerLeft = ref(false);
|
||||
const $q=useQuasar();
|
||||
const store = useFlowEditorStore();
|
||||
// ref関数を使ってtemplateとバインド
|
||||
const state=reactive({
|
||||
activeNode:{
|
||||
id:""
|
||||
},
|
||||
})
|
||||
const appDg = ref();
|
||||
const prevNodeIfo = ref({
|
||||
prevNode: {} as IActionNode,
|
||||
inputPoint: ""
|
||||
const prevNodeIfo=ref({
|
||||
prevNode:{} as IActionNode,
|
||||
inputPoint:""
|
||||
});
|
||||
// const refFlow = ref<ActionFlow|null>(null);
|
||||
const showAddAction = ref(false);
|
||||
const drawerRight = ref(false);
|
||||
const filter=ref("");
|
||||
const model = ref("");
|
||||
const addActionNode = (action: IActionNode) => {
|
||||
const showAddAction=ref(false);
|
||||
const drawerRight=ref(false);
|
||||
const model=ref("");
|
||||
const addActionNode=(action:IActionNode)=>{
|
||||
// refFlow.value?.actionNodes.push(action);
|
||||
store.currentFlow?.actionNodes.push(action);
|
||||
}
|
||||
const rootNode = computed(()=>{
|
||||
return store.currentFlow?.getRoot();
|
||||
});
|
||||
const minPanelWidth=computed(()=>{
|
||||
const root = store.currentFlow?.getRoot();
|
||||
if(store.currentFlow && root){
|
||||
return store.currentFlow?.getColumns(root) * 300 + 'px';
|
||||
}else{
|
||||
return "300px";
|
||||
}
|
||||
});
|
||||
|
||||
const addNode = (node: IActionNode, inputPoint: string) => {
|
||||
if (drawerRight.value) {
|
||||
drawerRight.value = false;
|
||||
}
|
||||
showAddAction.value = true;
|
||||
prevNodeIfo.value.prevNode = node;
|
||||
prevNodeIfo.value.inputPoint = inputPoint;
|
||||
store.currentFlow?.actionNodes.push(action);
|
||||
}
|
||||
|
||||
const onNodeSelected = (node: IActionNode) => {
|
||||
const addNode=(node:IActionNode,inputPoint:string)=>{
|
||||
if(drawerRight.value){
|
||||
drawerRight.value=false;
|
||||
}
|
||||
showAddAction.value=true;
|
||||
prevNodeIfo.value.prevNode=node;
|
||||
prevNodeIfo.value.inputPoint=inputPoint;
|
||||
}
|
||||
|
||||
const onNodeSelected=(node:IActionNode)=>{
|
||||
//右パネルが開いている場合、自動閉じる
|
||||
if (drawerRight.value && store.activeNode?.id !== node.id) {
|
||||
drawerRight.value = false;
|
||||
if(drawerRight.value && state.activeNode.id!==node.id){
|
||||
drawerRight.value=false;
|
||||
}
|
||||
store.setActiveNode(node);
|
||||
state.activeNode = node;
|
||||
}
|
||||
|
||||
const onNodeEdit = (node: IActionNode) => {
|
||||
store.setActiveNode(node);
|
||||
drawerRight.value = true;
|
||||
const onNodeEdit=(node:IActionNode)=>{
|
||||
state.activeNode = node;
|
||||
drawerRight.value=true;
|
||||
}
|
||||
|
||||
const onDeleteNode = (node: IActionNode) => {
|
||||
if (!store.currentFlow) return;
|
||||
const onDeleteNode=(node:IActionNode)=>{
|
||||
if(!store.currentFlow) return;
|
||||
//右パネルが開いている場合、自動閉じる
|
||||
if (drawerRight.value && store.activeNode?.id === node.id) {
|
||||
drawerRight.value = false;
|
||||
if(drawerRight.value && state.activeNode.id===node.id){
|
||||
drawerRight.value=false;
|
||||
}
|
||||
store.currentFlow?.removeNode(node);
|
||||
}
|
||||
|
||||
const onDeleteAllNextNodes = (node: IActionNode) => {
|
||||
if (!store.currentFlow) return;
|
||||
const onDeleteAllNextNodes=(node:IActionNode)=>{
|
||||
if(!store.currentFlow) return;
|
||||
//右パネルが開いている場合、自動閉じる
|
||||
if (drawerRight.value) {
|
||||
drawerRight.value = false;
|
||||
if(drawerRight.value){
|
||||
drawerRight.value=false;
|
||||
}
|
||||
store.currentFlow?.removeAllNext(node.id);
|
||||
}
|
||||
const closeDg = (val: any) => {
|
||||
console.log("Dialog closed->", val);
|
||||
const closeDg=(val :any)=>{
|
||||
console.log("Dialog closed->",val);
|
||||
if (val == 'OK') {
|
||||
const data = appDg.value.selected[0];
|
||||
const actionProps = JSON.parse(data.property);
|
||||
const outputPoint = JSON.parse(data.outputPoints);
|
||||
const action = new ActionNode(data.name, data.desc, "", outputPoint, actionProps);
|
||||
store.currentFlow?.addNode(action, prevNodeIfo.value.prevNode, prevNodeIfo.value.inputPoint);
|
||||
const data = appDg.value.selected[0];
|
||||
const actionProps=JSON.parse(data.property);
|
||||
const outputPoint =JSON.parse(data.outputPoints);
|
||||
const action = new ActionNode(data.name,data.desc,"",outputPoint,actionProps);
|
||||
store.currentFlow?.addNode(action, prevNodeIfo.value.prevNode,prevNodeIfo.value.inputPoint);
|
||||
}
|
||||
}
|
||||
/*
|
||||
*フローのデータをコピーする
|
||||
*/
|
||||
const onCopyFlow = () => {
|
||||
if (navigator.clipboard) {
|
||||
const jsonData =JSON.stringify(store.currentFlow) ;
|
||||
navigator.clipboard.writeText(jsonData).then(() => {
|
||||
console.log('Text successfully copied to clipboard');
|
||||
},
|
||||
(err) => {
|
||||
console.error('Error in copying text: ', err);
|
||||
});
|
||||
} else {
|
||||
console.log('Clipboard API not available');
|
||||
}
|
||||
};
|
||||
/**
|
||||
* デプロイ
|
||||
*/
|
||||
const onDeploy = async () => {
|
||||
if (store.appInfo === undefined || store.flows?.length === 0) {
|
||||
const onDeploy= async ()=>{
|
||||
if(store.appInfo===undefined || store.flows?.length===0){
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
caption: "エラー",
|
||||
caption:"エラー",
|
||||
message: `設定されたフローがありません。`
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
deployLoading.value = true;
|
||||
try{
|
||||
deployLoading.value=true;
|
||||
await store.deploy();
|
||||
deployLoading.value = false;
|
||||
deployLoading.value=false;
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
caption: "通知",
|
||||
caption:"通知",
|
||||
message: `デプロイを成功しました。`
|
||||
});
|
||||
} catch (error) {
|
||||
}catch(error){
|
||||
console.error(error);
|
||||
deployLoading.value = false;
|
||||
deployLoading.value=false;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
caption: "エラー",
|
||||
caption:"エラー",
|
||||
message: `デプロイが失敗しました。`
|
||||
})
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const onSaveFlow = async () => {
|
||||
const onSaveFlow = async ()=>{
|
||||
const targetFlow = store.selectedFlow;
|
||||
if (targetFlow === undefined) {
|
||||
if(targetFlow===undefined){
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
caption: "エラー",
|
||||
caption:"エラー",
|
||||
message: `編集中のフローがありません。`
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
saveLoading.value = true;
|
||||
try{
|
||||
saveLoading.value=true;
|
||||
await store.saveFlow(targetFlow);
|
||||
saveLoading.value = false;
|
||||
saveLoading.value=false;
|
||||
$q.notify({
|
||||
type: 'positive',
|
||||
caption: "通知",
|
||||
caption:"通知",
|
||||
message: `${targetFlow.getRoot()?.subTitle}のフロー設定を保存しました。`
|
||||
});
|
||||
} catch (error) {
|
||||
}catch(error){
|
||||
console.error(error);
|
||||
saveLoading.value = false;
|
||||
saveLoading.value=false;
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
caption: "エラー",
|
||||
caption:"エラー",
|
||||
message: `${targetFlow.getRoot()?.subTitle}のフローの設定の保存が失敗しました。`
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const fetchData = async () => {
|
||||
drawerLeft.value = true;
|
||||
if (store.appInfo === undefined) return;
|
||||
const fetchData = async ()=>{
|
||||
drawerLeft.value=true;
|
||||
if(store.appInfo===undefined) return;
|
||||
const flowCtrl = new FlowCtrl();
|
||||
const actionFlows = await flowCtrl.getFlows(store.appInfo?.appId);
|
||||
if (actionFlows && actionFlows.length > 0) {
|
||||
if(actionFlows && actionFlows.length>0){
|
||||
store.setFlows(actionFlows);
|
||||
}
|
||||
if (actionFlows && actionFlows.length == 1) {
|
||||
if(actionFlows && actionFlows.length==1){
|
||||
store.selectFlow(actionFlows[0]);
|
||||
}
|
||||
const root = actionFlows[0].getRoot();
|
||||
if (root) {
|
||||
store.setActiveNode(root);
|
||||
const root =actionFlows[0].getRoot();
|
||||
if(root){
|
||||
state.activeNode=root;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
authStore.toggleLeftMenu();
|
||||
fetchData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.app-selector {
|
||||
padding: 15px;
|
||||
z-index: 999;
|
||||
}
|
||||
.app-selector{
|
||||
padding:15px;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.flowchart {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.flow-toolbar {
|
||||
.flowchart{
|
||||
padding-top: 10px;
|
||||
}
|
||||
.flow-toolbar{
|
||||
opacity: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.event-tree .q-drawer {
|
||||
top: 50px;
|
||||
z-index: 999;
|
||||
}
|
||||
.expand{
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top: 50%;
|
||||
z-index: 9999;
|
||||
}
|
||||
.event-tree .q-drawer {
|
||||
top:50px;
|
||||
z-index: 999;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,13 +5,7 @@ const routes: RouteRecordRaw[] = [
|
||||
path: '/login',
|
||||
component: () => import('pages/LoginPage.vue')
|
||||
},
|
||||
{
|
||||
path:'/FlowChart',
|
||||
component:()=>import('layouts/MainLayout.vue'),
|
||||
children:[
|
||||
{path:'',component:()=>import('pages/FlowChart.vue')}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('layouts/MainLayout.vue'),
|
||||
@@ -22,7 +16,7 @@ const routes: RouteRecordRaw[] = [
|
||||
{ path: 'flow', component: () => import('pages/testFlow.vue') },
|
||||
{ path: 'FlowChartTest', component: () => import('pages/FlowChartTest.vue') },
|
||||
{ path: 'flowEditor', component: () => import('pages/FlowEditorPage.vue') },
|
||||
// { path: 'FlowChart', component: () => import('pages/FlowChart.vue') },
|
||||
{ path: 'FlowChart', component: () => import('pages/FlowChart.vue') },
|
||||
{ path: 'right', component: () => import('pages/testRight.vue') },
|
||||
{ path: 'domain', component: () => import('pages/TenantDomain.vue') },
|
||||
{ path: 'userdomain', component: () => import('pages/UserDomain.vue')},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { AppInfo ,IActionFlow, IActionNode} from 'src/types/ActionTypes';
|
||||
import { IKintoneEvent,KintoneEventManager } from 'src/types/KintoneEvents';
|
||||
import { AppInfo ,IActionFlow} from 'src/types/ActionTypes';
|
||||
import { kintoneEvents,IKintoneEvent,KintoneEventManager } from 'src/types/KintoneEvents';
|
||||
import {FlowCtrl } from '../control/flowctrl';
|
||||
|
||||
export interface FlowEditorState{
|
||||
@@ -8,21 +8,18 @@ export interface FlowEditorState{
|
||||
appInfo?:AppInfo;
|
||||
flows?:IActionFlow[];
|
||||
selectedFlow?:IActionFlow|undefined;
|
||||
activeNode:IActionNode|undefined;
|
||||
eventTree:KintoneEventManager;
|
||||
selectedEvent:IKintoneEvent|undefined;
|
||||
expandedScreen:any[];
|
||||
}
|
||||
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,
|
||||
eventTree:kintoneEvents,
|
||||
selectedEvent:undefined,
|
||||
expandedScreen:[]
|
||||
}),
|
||||
@@ -56,9 +53,6 @@ export const useFlowEditorStore = defineStore("flowEditor",{
|
||||
selectFlow(flow:IActionFlow){
|
||||
this.selectedFlow=flow;
|
||||
},
|
||||
setActiveNode(node:IActionNode){
|
||||
this.activeNode=node;
|
||||
},
|
||||
setApp(app:AppInfo){
|
||||
this.appInfo=app;
|
||||
},
|
||||
|
||||
@@ -8,7 +8,6 @@ export interface IUserState{
|
||||
token?:string;
|
||||
returnUrl:string;
|
||||
currentDomain:IDomainInfo;
|
||||
LeftDrawer:boolean;
|
||||
}
|
||||
|
||||
export const useAuthStore = defineStore({
|
||||
@@ -21,19 +20,10 @@ export const useAuthStore = defineStore({
|
||||
return {
|
||||
token,
|
||||
returnUrl: '',
|
||||
LeftDrawer:false,
|
||||
currentDomain: JSON.parse(localStorage.getItem('currentDomain')||"{}")
|
||||
}
|
||||
},
|
||||
getters:{
|
||||
toggleLeftDrawer():boolean{
|
||||
return this.LeftDrawer;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
toggleLeftMenu(){
|
||||
this.LeftDrawer=!this.LeftDrawer;
|
||||
},
|
||||
async login(username:string, password:string) {
|
||||
const params = new URLSearchParams();
|
||||
params.append('username', username);
|
||||
|
||||
@@ -16,9 +16,11 @@ export interface AppInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* 属性項目情報
|
||||
* アクションのプロパティ定義
|
||||
*/
|
||||
export interface IProp{
|
||||
export interface IActionProperty {
|
||||
component: string;
|
||||
props: {
|
||||
//プロパティ名
|
||||
name: string;
|
||||
//プロパティ表示名
|
||||
@@ -26,26 +28,9 @@ export interface IProp{
|
||||
placeholder: string;
|
||||
//入力提示・説明
|
||||
hint:string;
|
||||
//関連属性リスト
|
||||
connectProps:[{key:string,propName:string}]|undefined;
|
||||
//プロパティ設定値
|
||||
modelValue: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* アクションのプロパティ定義
|
||||
*/
|
||||
export interface IActionProperty {
|
||||
component: string;
|
||||
props: IProp;
|
||||
}
|
||||
/**
|
||||
* 変数オブジェクト
|
||||
*/
|
||||
export interface IActionVariable{
|
||||
actionName:string;
|
||||
displayName:string;
|
||||
name:string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* アクションタイプ定義
|
||||
@@ -55,7 +40,6 @@ export interface IActionNode {
|
||||
//アクション名
|
||||
name: string;
|
||||
title: string;
|
||||
varName:IProp|undefined;
|
||||
subTitle: string;
|
||||
inputPoint: string;
|
||||
//出力ポイント(条件分岐以外未使用)
|
||||
@@ -78,12 +62,10 @@ export interface IActionFlow {
|
||||
addNode(newNode: IActionNode, prevNode?: IActionNode, inputPoint?: string): IActionNode;
|
||||
removeNode(targetNode: IActionNode): boolean;
|
||||
removeAllNext(targetNodeId: string): void;
|
||||
getVarNames(currentNode:IActionNode):IActionVariable[];
|
||||
findNodeById(id: string): IActionNode | undefined;
|
||||
toJSON(): any;
|
||||
getRoot(): IActionNode | undefined;
|
||||
createNewId(): string;
|
||||
getColumns(node:IActionNode):number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +73,16 @@ export interface IActionFlow {
|
||||
*/
|
||||
class ActionProperty implements IActionProperty {
|
||||
component: string;
|
||||
props: IProp;
|
||||
props: {
|
||||
// プロパティ名
|
||||
name: string;
|
||||
// プロパティ表示名
|
||||
displayName: string;
|
||||
placeholder: string;
|
||||
hint:string;
|
||||
// プロパティ設定値
|
||||
modelValue: any;
|
||||
};
|
||||
|
||||
static defaultProperty(): IActionProperty {
|
||||
return new ActionProperty('InputText', 'displayName', '表示名', '表示を入力してください', '','');
|
||||
@@ -111,7 +102,6 @@ class ActionProperty implements IActionProperty {
|
||||
displayName: displayName,
|
||||
placeholder: placeholder,
|
||||
hint:hint,
|
||||
connectProps:undefined,
|
||||
modelValue: modelValue
|
||||
};
|
||||
}
|
||||
@@ -131,13 +121,6 @@ export class ActionNode implements IActionNode {
|
||||
get subTitle(): string {
|
||||
return this.name;
|
||||
};
|
||||
|
||||
//変数名
|
||||
get varName():IProp|undefined{
|
||||
const prop = this.actionProps.find((prop) => prop.props.name === "verName");
|
||||
return prop?.props;
|
||||
}
|
||||
|
||||
inputPoint: string;
|
||||
//出力ポイント(条件分岐以外未使用)
|
||||
outputPoints: Array<string>;
|
||||
@@ -185,7 +168,6 @@ export class RootAction implements IActionNode {
|
||||
title: string;
|
||||
subTitle: string;
|
||||
inputPoint: string;
|
||||
varName: IProp | undefined=undefined;
|
||||
//出力ポイント(条件分岐以外未使用)
|
||||
outputPoints: Array<string>;
|
||||
isRoot: boolean;
|
||||
@@ -243,7 +225,7 @@ export class ActionFlow implements IActionFlow {
|
||||
newNode.inputPoint = inputPoint;
|
||||
}
|
||||
if (prevNode !== undefined) {
|
||||
this.resetNodeRelation(prevNode, newNode, inputPoint || '');
|
||||
this.connectNodes(prevNode, newNode, inputPoint || '');
|
||||
} else {
|
||||
prevNode = this.actionNodes[this.actionNodes.length - 1];
|
||||
this.connectNodes(prevNode, newNode, inputPoint || '');
|
||||
@@ -287,29 +269,9 @@ export class ActionFlow implements IActionFlow {
|
||||
return false;
|
||||
}
|
||||
for (const [, id] of targetNode.nextNodeIds) {
|
||||
this.removeAll(id);
|
||||
this.removeAllNext(id);
|
||||
this.removeFromActionNodes(id);
|
||||
}
|
||||
targetNode.nextNodeIds.clear();
|
||||
}
|
||||
|
||||
/***
|
||||
* 目標ノードの次のノードを全部削除する
|
||||
*/
|
||||
removeAll(targetNodeId: string) {
|
||||
if (!targetNodeId || targetNodeId === '') {
|
||||
return;
|
||||
}
|
||||
const targetNode = this.findNodeById(targetNodeId);
|
||||
if (!targetNode) {
|
||||
return
|
||||
}
|
||||
if (targetNode.nextNodeIds.size == 0) {
|
||||
return
|
||||
}
|
||||
for (const [, id] of targetNode.nextNodeIds) {
|
||||
this.removeAll(id);
|
||||
}
|
||||
this.removeNode(targetNode);
|
||||
}
|
||||
|
||||
// 断开与前一个节点的连接
|
||||
@@ -357,7 +319,8 @@ export class ActionFlow implements IActionFlow {
|
||||
if (!nextNodeId) return;
|
||||
const nextNode = this.findNodeById(nextNodeId);
|
||||
if (!nextNode) return;
|
||||
this.connectNodes(prevNode,nextNode,targetNode.inputPoint || '');
|
||||
nextNode.prevNodeId = prevNode.id;
|
||||
prevNode.nextNodeIds.set(targetNode.inputPoint || '', nextNodeId);
|
||||
return;
|
||||
}
|
||||
//二つ以上の場合
|
||||
@@ -391,16 +354,15 @@ export class ActionFlow implements IActionFlow {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param prevNode ノード挿入時の接続をリセットする
|
||||
* @param prevNode ノードの接続をリセットする
|
||||
* @param newNode
|
||||
* @param inputPoint
|
||||
*/
|
||||
resetNodeRelation(prevNode: IActionNode, newNode: IActionNode, inputPoint?: string) {
|
||||
//元の次のノードを取得
|
||||
const originalNextNodeId = prevNode.nextNodeIds.get(inputPoint || '');
|
||||
//
|
||||
prevNode.nextNodeIds.set(inputPoint || '', newNode.id);
|
||||
newNode.prevNodeId = prevNode.id;
|
||||
newNode.inputPoint=inputPoint||'';
|
||||
const originalNextNodeId = prevNode.nextNodeIds.get(inputPoint || '');
|
||||
this.setNewNodeNextId(newNode, originalNextNodeId, inputPoint);
|
||||
}
|
||||
|
||||
@@ -412,18 +374,15 @@ export class ActionFlow implements IActionFlow {
|
||||
*/
|
||||
private setNewNodeNextId(newNode: IActionNode, originalNextNodeId: string | undefined, inputPoint?: string) {
|
||||
// 元の接続ノードが存在する
|
||||
if (!originalNextNodeId) {return;}
|
||||
const originNextNode = this.findNodeById(originalNextNodeId);
|
||||
if (!originNextNode) {return;}
|
||||
// 新しいノードの outputPoints に該当 inputPointが存在するか場合をチェックする
|
||||
if (newNode.outputPoints.includes(inputPoint || '')) {
|
||||
newNode.nextNodeIds.set(inputPoint || '', originalNextNodeId);
|
||||
originNextNode.prevNodeId=newNode.id;
|
||||
} else {
|
||||
// inputPointが存在しない場合、outputPointのポイントの任意ポートを選択する
|
||||
const alternativeOutputPoint = newNode.outputPoints.length > 0 ? newNode.outputPoints[0] : '';
|
||||
newNode.nextNodeIds.set(alternativeOutputPoint, originalNextNodeId);
|
||||
originNextNode.prevNodeId=newNode.id;
|
||||
if (originalNextNodeId) {
|
||||
// 新しいノードの outputPoints に該当 inputPointが存在するか場合をチェックする
|
||||
if (newNode.outputPoints.includes(inputPoint || '')) {
|
||||
newNode.nextNodeIds.set(inputPoint || '', originalNextNodeId);
|
||||
} else {
|
||||
// inputPointが存在しない場合、outputPointのポイントの任意ポートを選択する
|
||||
const alternativeOutputPoint = newNode.outputPoints.length > 0 ? newNode.outputPoints[0] : '';
|
||||
newNode.nextNodeIds.set(alternativeOutputPoint, originalNextNodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,36 +393,6 @@ export class ActionFlow implements IActionFlow {
|
||||
return this.actionNodes.find((node) => node.id === id);
|
||||
}
|
||||
|
||||
getVarNames(currentNode:IActionNode):IActionVariable[]{
|
||||
let varNames:IActionVariable[]=[];
|
||||
if(currentNode.prevNodeId!==undefined){
|
||||
const prevNode=this.findNodeById(currentNode.prevNodeId);
|
||||
if(prevNode!==undefined){
|
||||
varNames = this.getPrevVarNames(prevNode);
|
||||
}
|
||||
}
|
||||
return varNames;
|
||||
}
|
||||
|
||||
getPrevVarNames(prevNode:IActionNode):IActionVariable[]{
|
||||
let varNames:IActionVariable[]=[];
|
||||
if(prevNode.varName!==undefined && prevNode.varName.modelValue){
|
||||
varNames.unshift({
|
||||
actionName:prevNode.name,
|
||||
displayName:prevNode.varName.displayName,
|
||||
name:prevNode.varName.modelValue
|
||||
});
|
||||
}
|
||||
if(prevNode.prevNodeId!==undefined){
|
||||
const prevPrevNode=this.findNodeById(prevNode.prevNodeId);
|
||||
if(prevPrevNode!==undefined){
|
||||
const prevVars = this.getPrevVarNames(prevPrevNode);
|
||||
varNames=[...prevVars,...varNames];
|
||||
}
|
||||
}
|
||||
return varNames;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
id: this.id,
|
||||
@@ -471,27 +400,12 @@ export class ActionFlow implements IActionFlow {
|
||||
const { nextNodeIds, ...rest } = node;
|
||||
return {
|
||||
...rest,
|
||||
nextNodeIds: Object.fromEntries(nextNodeIds)
|
||||
nextNodeIds: Array.from(nextNodeIds.entries())
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
getColumns(node:IActionNode):number{
|
||||
let result= 1;
|
||||
if(node.outputPoints && node.outputPoints.length>1){
|
||||
result += node.outputPoints.length -1;
|
||||
}
|
||||
let nextNode;
|
||||
for (const [key, id] of node.nextNodeIds) {
|
||||
nextNode=this.findNodeById(id);
|
||||
if(nextNode){
|
||||
result +=this.getColumns(nextNode)-1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
getRoot(): IActionNode | undefined {
|
||||
return this.actionNodes.find(node => node.isRoot)
|
||||
}
|
||||
@@ -505,9 +419,9 @@ export class ActionFlow implements IActionFlow {
|
||||
const parsedObject = JSON.parse(json);
|
||||
|
||||
const actionNodes = parsedObject.actionNodes.map((node: any) => {
|
||||
const nodeClass = !node.isRoot ? new ActionNode(node.name, node.title, node.inputPoint, node.outputPoints, node.actionProps)
|
||||
const nodeClass = !node.isRoot ? new ActionNode(node.name, node.title, node.inputPoint, node.outputPoint, node.actionProps)
|
||||
: new RootAction(node.name, node.title, node.subTitle);
|
||||
nodeClass.nextNodeIds = new Map<string,string>(Object.entries(node.nextNodeIds));
|
||||
nodeClass.nextNodeIds = new Map(node.nextNodeIds);
|
||||
nodeClass.prevNodeId = node.prevNodeId;
|
||||
nodeClass.id = node.id;
|
||||
return nodeClass;
|
||||
|
||||
@@ -1,197 +1,112 @@
|
||||
import { publicDecrypt } from 'crypto';
|
||||
import {IActionFlow} from './ActionTypes';
|
||||
export interface IKintoneEventNode {
|
||||
export interface TreeNode {
|
||||
label: string;
|
||||
header:string;
|
||||
eventId:string;
|
||||
parentId:string;
|
||||
}
|
||||
|
||||
export interface IKintoneEvent extends IKintoneEventNode {
|
||||
export interface IKintoneEvent extends TreeNode {
|
||||
eventId: string;
|
||||
hasFlow: boolean;
|
||||
flowData?: IActionFlow;
|
||||
}
|
||||
|
||||
export interface IKintoneEventGroup extends IKintoneEventNode {
|
||||
events: IKintoneEventNode[];
|
||||
export interface IKintoneScreen extends TreeNode {
|
||||
label: string;
|
||||
events: IKintoneEvent[];
|
||||
}
|
||||
|
||||
|
||||
export class kintoneEvent implements IKintoneEvent{
|
||||
eventId: string;
|
||||
parentId:string;
|
||||
get hasFlow(): boolean{
|
||||
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){
|
||||
constructor({eventId,label}:{eventId:string,label:string}){
|
||||
this.eventId=eventId;
|
||||
this.label=label;
|
||||
this.parentId=parentId;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class kintoneEventGroup implements IKintoneEventGroup{
|
||||
eventId: string;
|
||||
parentId:string;
|
||||
label: string;
|
||||
events: IKintoneEventNode[];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class kintoneEventForChange implements IKintoneEventGroup{
|
||||
eventId: string;
|
||||
parentId:string;
|
||||
label: string;
|
||||
events: IKintoneEventNode[];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class KintoneEventManager {
|
||||
public screens: IKintoneEventGroup[];
|
||||
public screens: IKintoneScreen[];
|
||||
|
||||
constructor() {
|
||||
this.screens = this.getKintoneEvents();
|
||||
constructor(screens: IKintoneScreen[]) {
|
||||
this.screens = screens;
|
||||
}
|
||||
|
||||
public bindFlows(flows:IActionFlow[]){
|
||||
this.screens=this.getKintoneEvents();
|
||||
for (const screen of this.screens) {
|
||||
screen.events.forEach((ev)=>ev.flowData=undefined);
|
||||
}
|
||||
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;
|
||||
const event = this.findEventById(eventId);
|
||||
if(event!==null){
|
||||
event.flowData=flow;
|
||||
}else{
|
||||
//EventGroupのIDを取得
|
||||
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;
|
||||
groupEvent.events.push(newEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public findEventById(eventId: string): IKintoneEventNode | null {
|
||||
const screen=this.findScreen(eventId);
|
||||
if(screen) {return screen;}
|
||||
public findEventById(eventId: string): IKintoneEvent | null {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public findScreen(eventId:string):IKintoneEventGroup|undefined{
|
||||
return this.screens.find(screen=>screen.eventId==eventId);
|
||||
}
|
||||
|
||||
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"),
|
||||
],"")
|
||||
];
|
||||
public findScreen(eventId:string):IKintoneScreen|null{
|
||||
for (const screen of this.screens) {
|
||||
if(screen.events.some((ev:IKintoneEvent)=>ev.eventId===eventId)){
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// export const kintoneEvents:KintoneEventManager = new KintoneEventManager([
|
||||
// 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.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.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.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.customButtonClick','ボタンをクリックした時',[],"app.record.index"),
|
||||
// ],"")
|
||||
// ]);
|
||||
export const kintoneEvents:KintoneEventManager = new KintoneEventManager([
|
||||
{
|
||||
label:'レコード追加画面',
|
||||
events:[
|
||||
new kintoneEvent({label:'レコード追加画面を表示した後',eventId:'app.record.create.show'}),
|
||||
new kintoneEvent({label:'保存をクリックしたとき',eventId:'app.record.create.submit'}),
|
||||
new kintoneEvent({label:'保存が成功したとき',eventId:'app.record.create.submit.success'}),
|
||||
new kintoneEvent({label:'フィールドの値を変更したとき',eventId:'app.record.create.change'}),
|
||||
]
|
||||
},
|
||||
{
|
||||
label:'レコード詳細画面',
|
||||
events:[
|
||||
new kintoneEvent({label:'レコード詳細画面を表示した後',eventId:'app.record.detail.show'}),
|
||||
new kintoneEvent({label:'レコードを削除するとき',eventId:'app.record.detail.delete.submit'}),
|
||||
new kintoneEvent({label:'プロセス管理のアクションを実行したとき',eventId:'app.record.detail.process.proceed'}),
|
||||
]
|
||||
},
|
||||
{
|
||||
label:'レコード編集画面',
|
||||
events:[new kintoneEvent({label:'レコード編集画面を表示した後',eventId:'app.record.edit.show'}),
|
||||
new kintoneEvent({label:'保存をクリックしたとき',eventId:'app.record.edit.submit'}),
|
||||
new kintoneEvent({label:'保存が成功したとき',eventId:'app.record.edit.submit.success'}),
|
||||
new kintoneEvent({label:'フィールドの値を変更したとき',eventId:'app.record.edit.change'}),
|
||||
]
|
||||
},
|
||||
{
|
||||
label:'レコード一覧画面',
|
||||
events:[
|
||||
new kintoneEvent({label:'一覧画面を表示した後', eventId:'app.record.index.show'}),
|
||||
new kintoneEvent({label:'インライン編集を開始したとき',eventId:'app.record.index.edit.show'}),
|
||||
new kintoneEvent({label:'インライン編集のフィールド値を変更したとき', eventId:'app.record.index.edit.change'}),
|
||||
new kintoneEvent({label:'インライン編集の【保存】をクリックしたとき',eventId:'app.record.index.edit.submit'}),
|
||||
new kintoneEvent({label:'インライン編集の保存が成功したとき', eventId:'app.record.index.edit.submit.success'}),
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
10
node_modules/.yarn-integrity
generated
vendored
10
node_modules/.yarn-integrity
generated
vendored
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"systemParams": "win32-x64-115",
|
||||
"modulesFolders": [],
|
||||
"flags": [],
|
||||
"linkedModules": [],
|
||||
"topLevelPatterns": [],
|
||||
"lockfileEntries": {},
|
||||
"files": [],
|
||||
"artifacts": {}
|
||||
}
|
||||
16
plugin/kintone-addins/package-lock.json
generated
16
plugin/kintone-addins/package-lock.json
generated
@@ -8,8 +8,7 @@
|
||||
"name": "kintone-addins",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"jquery": "^3.7.1",
|
||||
"yarn": "^1.22.22"
|
||||
"jquery": "^3.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jquery": "^3.5.24",
|
||||
@@ -796,19 +795,6 @@
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/yarn": {
|
||||
"version": "1.22.22",
|
||||
"resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz",
|
||||
"integrity": "sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"yarn": "bin/yarn.js",
|
||||
"yarnpkg": "bin/yarn.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "tsc && set \"SOURCE_MAP=true\" && vite build && vite preview",
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build && xcopy dist\\*.js ..\\..\\backend\\Temp\\ /E /I /Y",
|
||||
"build:dev": "tsc && set \"SOURCE_MAP=true\" && vite build && xcopy dist\\*.js ..\\..\\backend\\Temp\\ /E /I /Y",
|
||||
"preview": "vite preview",
|
||||
"ngrok":"ngrok http http://localhost:4173/",
|
||||
"vite":"vite dev"
|
||||
"build:dev":"tsc && set \"SOURCE_MAP=true\" && vite build && xcopy dist\\*.js ..\\..\\backend\\Temp\\ /E /I /Y",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jquery": "^3.5.24",
|
||||
@@ -19,7 +17,6 @@
|
||||
"vite": "^4.4.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"jquery": "^3.7.1",
|
||||
"yarn": "^1.22.22"
|
||||
"jquery": "^3.7.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,10 +68,6 @@
|
||||
| modelValue | 空文字 | コンポーネントの初期値を設定します。<br>初期設定ないの場合は空文字で設定する。
|
||||
| name | field | 属性の設定値の名前です。 |
|
||||
| placeholder | 対象項目を選択してください| 入力フィールドに表示されるプレースホルダーのテキストです。この場合は設定されていません。 |
|
||||
| hint | 説明文| 長い説明文を設定することが可能です。(markdown形式サポート予定、現在HTML可能) |
|
||||
| selectType |`single` or `multiple`| フィールド選択・他のアプリのフィールド選択の選択モードを設定する |
|
||||
|
||||
|
||||
|
||||
### 使用可能なコンポーネント
|
||||
| No. | コンポーネント名 | コンポーネントタイプ | 説明 |
|
||||
@@ -82,10 +78,9 @@
|
||||
| 4 | フィールド選択 | FieldInput | システムのフィールドを選択するための入力コンポーネントです。 |
|
||||
| 5 | 選択リスト | SelectBox | 複数のオプションから選択するためのドロップダウンリストです。 |
|
||||
| 6 | 条件式設定 | ConditionInput | 条件式やロジックを入力するためのコンポーネントです。 |
|
||||
| 7 | イベント設定 |EventSetter | ボタンイベント設定のコンポーネントです。 |
|
||||
| 8 | 色選択 | ColorPicker | 色を設定する(追加予定中) |
|
||||
| 9 | 他のアプリのフィールド選択 | AppFieldPicker | 他のアプリのフィールドを選択する(追加予定中) |
|
||||
| 10 |ユーザー選択 | UserPicker | ユーザーを選択する(追加予定中) |
|
||||
| 7 | 色選択 | ColorPicker | 色を設定する(追加予定中) |
|
||||
| 8 | 他のアプリのフィールド選択 | AppFieldPicker | 他のアプリのフィールドを選択する(追加予定中) |
|
||||
| 9 |ユーザー選択 | UserPicker | ユーザーを選択する(追加予定中) |
|
||||
|
||||
## 2.アクションアドインの開発
|
||||
|
||||
@@ -268,28 +263,4 @@ npm run build:dev
|
||||
|
||||
- デプロイの確認:
|
||||
- Azure App Service 拡張機能でデプロイが完了したことを確認します。
|
||||
- ka-addin の URL にアクセスしてアプリケーションが正常に動作しているか確認します。
|
||||
|
||||
3. **ローカルでプラグインをテストする**
|
||||
1. kintone-addinsをPreviewで起動する
|
||||
```bash
|
||||
yarn build:dev
|
||||
yarn preview
|
||||
#またはyarn devは yarn build:dev + yarn preview と同じです
|
||||
yarn dev
|
||||
```
|
||||
2. **ngrokをインストールする**
|
||||
1. [ngrok の公式ウェブサイト](https://ngrok.com/)にアクセスします。
|
||||
2. 「Sign up」をクリックしてアカウントを登録するか、既存のアカウントにログインします。
|
||||
3. 登録またはログイン後、ダッシュボードに進み、ダウンロードリンクが表示されます。操作システム(Windows、macOS、Linux)に応じて、適切なバージョンを選択してダウンロードします。
|
||||
4. ダウンロード後、`.zip` ファイルを解凍します。
|
||||
5. ngrok を設定する
|
||||
1. ngrok ダッシュボードにログインし、ホームページで認証トークンを見つけます。
|
||||
2. ターミナル(またはコマンドプロンプト)を開き、以下のコマンドを実行して認証トークンを追加します:
|
||||
```bash
|
||||
ngrok config add-authtoken <認証トークン>
|
||||
```
|
||||
6. ngrok を起動する
|
||||
```bash
|
||||
ngrok https http://localhost:4173/
|
||||
```
|
||||
- ka-addin の URL にアクセスしてアプリケーションが正常に動作しているか確認します。
|
||||
@@ -7,6 +7,7 @@ declare global {
|
||||
interface Window { $format: any; }
|
||||
}
|
||||
|
||||
|
||||
interface IAutoNumberingProps{
|
||||
//文書番号を格納する
|
||||
field:IField;
|
||||
@@ -34,13 +35,7 @@ export class AutoNumbering implements IAction{
|
||||
globalThis.window.$format=this.format;
|
||||
this.register();
|
||||
}
|
||||
/**
|
||||
* アクションの処理を実装する
|
||||
* @param actionNode アクションノード
|
||||
* @param event Kintoneのイベント
|
||||
* @param context コンテキスト(レコード、変数情報を持っている)
|
||||
* @returns
|
||||
*/
|
||||
|
||||
async process(actionNode:IActionNode,event:any,context:IContext):Promise<IActionResult> {
|
||||
let result={
|
||||
canNext:false,
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
|
||||
import { actionAddins } from ".";
|
||||
import $ from 'jquery';
|
||||
import { IAction, IActionProperty, IActionNode, IActionResult } from "../types/ActionTypes";
|
||||
/**
|
||||
* ボタン配置属性定義
|
||||
*/
|
||||
interface IButtonAddProps {
|
||||
//ボタン表示名
|
||||
buttonName: string;
|
||||
//配置位置
|
||||
position: string;
|
||||
//イベント名
|
||||
eventName:string
|
||||
}
|
||||
|
||||
export class ButtonAddAction implements IAction {
|
||||
name: string;
|
||||
actionProps: IActionProperty[];
|
||||
props: IButtonAddProps;
|
||||
constructor() {
|
||||
this.name = "ボタンの配置";
|
||||
this.actionProps = [];
|
||||
this.props = {
|
||||
buttonName: '',
|
||||
position: '',
|
||||
eventName:''
|
||||
}
|
||||
this.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* アクションの実行を呼び出す
|
||||
* @param actionNode
|
||||
* @param event
|
||||
* @returns
|
||||
*/
|
||||
async process(actionNode: IActionNode, event: any): Promise<IActionResult> {
|
||||
let result = {
|
||||
canNext: true,
|
||||
result: false
|
||||
};
|
||||
try {
|
||||
this.actionProps = actionNode.actionProps;
|
||||
if (!('buttonName' in actionNode.ActionValue) && !('position' in actionNode.ActionValue)) {
|
||||
return result
|
||||
}
|
||||
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);
|
||||
}
|
||||
const button =$(`<button id='${this.props.eventName}' class='alc-button-normal' >${this.props.buttonName}</button>`);
|
||||
if(this.props.position==="一番左に追加する"){
|
||||
$(menuSpace).prepend(button);
|
||||
}else{
|
||||
$(menuSpace).append(button);
|
||||
}
|
||||
const clickEventName = `${event.type}.customButtonClick.${this.props.eventName}`;
|
||||
button.on("click",()=>{
|
||||
$(document).trigger(clickEventName,event);
|
||||
});
|
||||
return result;
|
||||
} catch (error) {
|
||||
event.error = error;
|
||||
console.error(error);
|
||||
result.canNext = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
register(): void {
|
||||
actionAddins[this.name] = this;
|
||||
}
|
||||
|
||||
}
|
||||
new ButtonAddAction();
|
||||
@@ -1,109 +0,0 @@
|
||||
|
||||
import { actionAddins } from ".";
|
||||
import { IAction,IActionResult, IActionNode, IActionProperty, IContext } from "../types/ActionTypes";
|
||||
import { ConditionTree } from '../types/Conditions';
|
||||
/**
|
||||
* アクションの属性定義
|
||||
*/
|
||||
interface ICondition{
|
||||
condition:string;
|
||||
verName:string;
|
||||
}
|
||||
/**
|
||||
* 条件分岐アクション
|
||||
*/
|
||||
export class ConditionAction implements IAction{
|
||||
name: string;
|
||||
actionProps: IActionProperty[];
|
||||
props:ICondition;
|
||||
constructor(){
|
||||
this.name="条件式";
|
||||
this.actionProps=[];
|
||||
this.props={
|
||||
condition:'',
|
||||
verName:''
|
||||
}
|
||||
//アクションを登録する
|
||||
this.register();
|
||||
}
|
||||
/**
|
||||
* アクションの実行を呼び出す
|
||||
* @param actionNode
|
||||
* @param event
|
||||
* @returns
|
||||
*/
|
||||
async process(actionNode:IActionNode,event:any,context:IContext):Promise<IActionResult> {
|
||||
let result={
|
||||
canNext:true,
|
||||
result:''
|
||||
};
|
||||
try{
|
||||
//属性設定を取得する
|
||||
this.actionProps=actionNode.actionProps;
|
||||
if (!('condition' in actionNode.ActionValue) && !('verName' in actionNode.ActionValue)) {
|
||||
return result
|
||||
}
|
||||
this.props = actionNode.ActionValue as ICondition;
|
||||
//条件式の計算結果を取得
|
||||
const conditionResult = this.getConditionResult(context);
|
||||
console.log("条件計算結果:",conditionResult);
|
||||
if(conditionResult){
|
||||
result= {
|
||||
canNext:true,
|
||||
result:'はい'
|
||||
}
|
||||
}else{
|
||||
result= {
|
||||
canNext:true,
|
||||
result:'いいえ'
|
||||
}
|
||||
}
|
||||
if(this.props.verName){
|
||||
context.variables[this.props.verName]=result.result;
|
||||
}
|
||||
return result;
|
||||
}catch(error){
|
||||
event.error=error;
|
||||
console.error(error);
|
||||
result.canNext=false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param context 条件式を実行する
|
||||
* @returns
|
||||
*/
|
||||
getConditionResult(context:any):boolean{
|
||||
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 ConditionAction();
|
||||
@@ -1,75 +0,0 @@
|
||||
import { actionAddins } from ".";
|
||||
import { IAction,IActionResult, IActionNode, IActionProperty, IField} from "../types/ActionTypes";
|
||||
/**
|
||||
* アクションの属性定義
|
||||
*/
|
||||
interface IStrCountCheckProps{
|
||||
field:IField;//チェックするフィールドの対象
|
||||
message:string;//エラーメッセージ
|
||||
strExpression:string;//
|
||||
}
|
||||
/**
|
||||
* 正規表現チェックアクション
|
||||
*/
|
||||
export class StrCountCheckAciton implements IAction{
|
||||
name: string;
|
||||
actionProps: IActionProperty[];
|
||||
props:IStrCountCheckProps;
|
||||
constructor(){
|
||||
this.name="文字数チェック";
|
||||
this.actionProps=[];
|
||||
this.props={
|
||||
field:{code:''},
|
||||
message:'',
|
||||
strExpression:''
|
||||
}
|
||||
//アクションを登録する
|
||||
this.register();
|
||||
}
|
||||
/**
|
||||
* アクションの実行を呼び出す
|
||||
* @param actionNode
|
||||
* @param event
|
||||
* @returns
|
||||
*/
|
||||
async process(actionNode:IActionNode,event:any):Promise<IActionResult> {
|
||||
let result={
|
||||
canNext:true,
|
||||
result:false
|
||||
};
|
||||
try{
|
||||
//属性設定を取得する
|
||||
this.actionProps=actionNode.actionProps;
|
||||
if (!('field' in actionNode.ActionValue) && !('message' in actionNode.ActionValue) && !('strExpression'in actionNode.ActionValue)) {
|
||||
return result
|
||||
}
|
||||
|
||||
this.props = actionNode.ActionValue as IStrCountCheckProps;
|
||||
//条件式の計算結果を取得
|
||||
const record = event.record;
|
||||
const value = record[this.props.field.code].value;
|
||||
const strCheck = this.props.strExpression;
|
||||
if(value === undefined || value === '' ){
|
||||
return result;
|
||||
}else if(strCheck < value.length){
|
||||
record[this.props.field.code].error = this.props.message;
|
||||
}else{
|
||||
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 StrCountCheckAciton();
|
||||
@@ -2,26 +2,24 @@
|
||||
import { actionAddins } from ".";
|
||||
import { IAction, IActionProperty, IActionNode, IContext, IActionResult } from "../types/ActionTypes";
|
||||
import { ConditionTree } from '../types/Conditions';
|
||||
/**
|
||||
* アクションの属性定義
|
||||
*/
|
||||
|
||||
interface IErrorShowProps {
|
||||
message: string;
|
||||
condition: string;
|
||||
}
|
||||
}
|
||||
|
||||
export class ErrorShowAction implements IAction {
|
||||
name: string;
|
||||
actionProps: IActionProperty[]; //调用从import导入关于显示类的定义
|
||||
props: IErrorShowProps;//从上方的interface 定义这个props所需要接受的属性
|
||||
constructor() { //解构函数定义需要的类名
|
||||
name: string;
|
||||
actionProps: IActionProperty[];
|
||||
props: IErrorShowProps;
|
||||
constructor() {
|
||||
this.name = "エラー表示";
|
||||
this.actionProps = [];
|
||||
this.props = {
|
||||
message: '',
|
||||
condition: ''
|
||||
}
|
||||
this.register(); //重置以上注册表
|
||||
this.register();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,20 +28,20 @@ export class ErrorShowAction implements IAction {
|
||||
* @param event
|
||||
* @returns
|
||||
*/
|
||||
async process(actionNode: IActionNode, event: any, context: IContext): Promise<IActionResult> { //异步处理某函数下的:xx属性
|
||||
let result = {
|
||||
async process(actionNode: IActionNode, event: any, context: IContext): Promise<IActionResult> {
|
||||
let result = {
|
||||
canNext: true,
|
||||
result: false
|
||||
};
|
||||
try { //尝试执行以下代码部分
|
||||
try {
|
||||
this.actionProps = actionNode.actionProps;
|
||||
if (!('message' in actionNode.ActionValue) && !('condition' in actionNode.ActionValue)) { //如果message以及condition两者都不存在的情况下return
|
||||
if (!('message' in actionNode.ActionValue) && !('condition' in actionNode.ActionValue)) {
|
||||
return result
|
||||
}
|
||||
this.props = actionNode.ActionValue as IErrorShowProps;
|
||||
const conditionResult = this.getConditionResult(context);
|
||||
this.props = actionNode.ActionValue as IErrorShowProps;
|
||||
const conditionResult = this.getConditionResult(context);
|
||||
if (conditionResult) {
|
||||
event.error = this.props.message;
|
||||
event.error = this.props.message
|
||||
} else {
|
||||
result = {
|
||||
canNext: false,
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
import { actionAddins } from ".";
|
||||
import { IAction, IActionResult, IActionNode, IActionProperty, IField } from "../types/ActionTypes";
|
||||
/**
|
||||
* アクションの属性定義
|
||||
*/
|
||||
interface IMailCheckProps {
|
||||
field: IField;//チェックするフィールドの対象
|
||||
message: string;//エラーメッセージ
|
||||
}
|
||||
/**
|
||||
* メールアドレスチェックアクション
|
||||
*/
|
||||
export class MailCheckAction implements IAction {
|
||||
name: string;
|
||||
actionProps: IActionProperty[];
|
||||
props: IMailCheckProps;
|
||||
constructor() {
|
||||
this.name = "メールアドレスチェック";
|
||||
this.actionProps = [];
|
||||
this.props = {
|
||||
field: { code: '' },
|
||||
message: '',
|
||||
|
||||
}
|
||||
//アクションを登録する
|
||||
this.register();
|
||||
}
|
||||
/**
|
||||
* アクションの実行を呼び出す
|
||||
* @param actionNode
|
||||
* @param event
|
||||
* @returns
|
||||
*/
|
||||
async process(actionNode: IActionNode, event: any): Promise<IActionResult> {
|
||||
let result = {
|
||||
canNext: true,
|
||||
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) {
|
||||
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 (!/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value)) {
|
||||
console.log('厳格');
|
||||
record[this.props.field.code].error = this.props.message;
|
||||
}
|
||||
} else if (emailAction?.props.modelValue === 'ゆるめ') {
|
||||
if (!/^[^@]+@[^@]+$/.test(value)) {
|
||||
console.log('ゆるめ');
|
||||
|
||||
record[this.props.field.code].error = this.props.message;
|
||||
|
||||
}
|
||||
} else {
|
||||
result = {
|
||||
canNext: true,
|
||||
result: true
|
||||
}
|
||||
}
|
||||
console.log(record[this.props.field.code]);
|
||||
return result;
|
||||
} catch (error) {
|
||||
event.error = error;
|
||||
console.error(error);
|
||||
result.canNext = false;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
register(): void {
|
||||
actionAddins[this.name] = this;
|
||||
}
|
||||
|
||||
}
|
||||
new MailCheckAction();
|
||||
@@ -1,72 +0,0 @@
|
||||
import { actionAddins } from ".";
|
||||
import { IAction,IActionResult, IActionNode, IActionProperty, IField} from "../types/ActionTypes";
|
||||
/**
|
||||
* アクションの属性定義
|
||||
*/
|
||||
interface IRegularCheckProps{
|
||||
field:IField;//チェックするフィールドの対象
|
||||
message:string;//エラーメッセージ
|
||||
regExpression:string;//正規表現式
|
||||
}
|
||||
/**
|
||||
* 正規表現チェックアクション
|
||||
*/
|
||||
export class RegularCheckAction implements IAction{
|
||||
name: string;
|
||||
actionProps: IActionProperty[];
|
||||
props:IRegularCheckProps;
|
||||
constructor(){
|
||||
this.name="正規表現チェック";
|
||||
this.actionProps=[];
|
||||
this.props={
|
||||
field:{code:''},
|
||||
message:'',
|
||||
regExpression:''
|
||||
}
|
||||
//アクションを登録する
|
||||
this.register();
|
||||
}
|
||||
/**
|
||||
* アクションの実行を呼び出す
|
||||
* @param actionNode
|
||||
* @param event
|
||||
* @returns
|
||||
*/
|
||||
async process(actionNode:IActionNode,event:any):Promise<IActionResult> {
|
||||
let result={
|
||||
canNext:true,
|
||||
result:false
|
||||
};
|
||||
try{
|
||||
//属性設定を取得する
|
||||
this.actionProps=actionNode.actionProps;
|
||||
if (!('field' in actionNode.ActionValue) && !('message' in actionNode.ActionValue) && !('regExpression'in actionNode.ActionValue)) {
|
||||
return result
|
||||
}
|
||||
this.props = actionNode.ActionValue as IRegularCheckProps;
|
||||
//条件式の計算結果を取得
|
||||
const record = event.record;
|
||||
const value = record[this.props.field.code].value;
|
||||
const regex = new RegExp(this.props.regExpression);
|
||||
if(!regex.test(value)){
|
||||
record[this.props.field.code].error=this.props.message;
|
||||
}else{
|
||||
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 RegularCheckAction();
|
||||
@@ -14,58 +14,14 @@ declare const alcflow : {
|
||||
};
|
||||
|
||||
$(function (){
|
||||
const getChangeEvents=(events:string[])=>{
|
||||
return events.filter((event)=>event.includes(".change."));
|
||||
}
|
||||
const getClickEvents=(events:string[])=>{
|
||||
return events.filter((event)=>event.includes(".customButtonClick."));
|
||||
}
|
||||
const getKintoneEvents=(events:string[])=>{
|
||||
return events.filter((event)=>{
|
||||
return !event.includes(".customButtonClick.") && !event.includes(".change.")
|
||||
});
|
||||
}
|
||||
const events=Object.keys(alcflow);
|
||||
const changeEvents = getChangeEvents(events);
|
||||
const clickEvents = getClickEvents(events);
|
||||
const kintoneEvents = getKintoneEvents(events);
|
||||
if(kintoneEvents.length>0 ){
|
||||
//通常Kintoneイベントをバンド
|
||||
kintone.events.on(kintoneEvents,async (event:any)=>{
|
||||
const flowinfo = alcflow[event.type];
|
||||
const flow=ActionFlow.fromJSON(flowinfo.content);
|
||||
if(flow!==undefined){
|
||||
const process = new ActionProcess(event.type,flow,event);
|
||||
await process.exec();
|
||||
}
|
||||
return event;
|
||||
});
|
||||
}
|
||||
if(changeEvents.length>0){
|
||||
//値変更イベントをバンドする
|
||||
kintone.events.on(changeEvents,(event:any)=>{
|
||||
const flowinfo = alcflow[event.type];
|
||||
const flow=ActionFlow.fromJSON(flowinfo.content);
|
||||
if(flow!==undefined){
|
||||
const process = new ActionProcess(event.type,flow,event);
|
||||
process.exec();
|
||||
}
|
||||
return event;
|
||||
});
|
||||
}
|
||||
if(clickEvents.length>0){
|
||||
clickEvents.forEach((eventName:string)=>{
|
||||
$(document).on(eventName,async ()=>{
|
||||
const event=kintone.app.record.get();
|
||||
const flowinfo = alcflow[eventName];
|
||||
const flow=ActionFlow.fromJSON(flowinfo.content);
|
||||
if(flow!==undefined){
|
||||
const process = new ActionProcess(eventName,flow,event);
|
||||
await process.exec();
|
||||
}
|
||||
const record = event.record;
|
||||
kintone.app.record.set({record})
|
||||
});
|
||||
});
|
||||
}
|
||||
kintone.events.on(events,async (event:any)=>{
|
||||
const flowinfo = alcflow[event.type];
|
||||
const flow=ActionFlow.fromJSON(flowinfo.content);
|
||||
if(flow!==undefined){
|
||||
const process = new ActionProcess(event.type,flow,event);
|
||||
await process.exec();
|
||||
}
|
||||
return event;
|
||||
});
|
||||
});
|
||||
@@ -157,19 +157,19 @@ export class ActionNode implements IActionNode {
|
||||
prevNodeId?: string;
|
||||
nextNodeIds: Map<string, string>;
|
||||
constructor(
|
||||
{id,name,title,inputPoint,outputPoints,actionProps}:
|
||||
{id,name,title,inputPoint,outputPoint,actionProps}:
|
||||
{
|
||||
id:string,
|
||||
name: string,
|
||||
title: string,
|
||||
inputPoint: string,
|
||||
outputPoints: Array<string>,
|
||||
outputPoint: Array<string>,
|
||||
actionProps: Array<IActionProperty>}
|
||||
) {
|
||||
this.id=id;
|
||||
this.name = name;
|
||||
this.inputPoint = inputPoint;
|
||||
this.outputPoints = outputPoints;
|
||||
this.outputPoints = outputPoint;
|
||||
const defProp = ActionProperty.defaultProperty();
|
||||
defProp.props.modelValue = title;
|
||||
this.actionProps = actionProps;
|
||||
@@ -257,7 +257,7 @@ export class ActionFlow implements IActionFlow {
|
||||
const actionNodes = parsedObject.actionNodes.map((node: any) => {
|
||||
const nodeClass = !node.isRoot ? new ActionNode(node)
|
||||
: new RootAction(node);
|
||||
nodeClass.nextNodeIds = new Map<string,string>(Object.entries(node.nextNodeIds));
|
||||
nodeClass.nextNodeIds = new Map(node.nextNodeIds);
|
||||
nodeClass.prevNodeId = node.prevNodeId;
|
||||
nodeClass.id = node.id;
|
||||
return nodeClass;
|
||||
|
||||
@@ -324,17 +324,12 @@ export class ConditionTree {
|
||||
*/
|
||||
getObjectValue(object:any,context:IContext){
|
||||
if(!object || typeof object!=="object" || !("objectType" in object)){
|
||||
return undefined;
|
||||
return object;
|
||||
}
|
||||
if(object.objectType==='field'){
|
||||
const fieldValue = context.record[object.code];
|
||||
if(fieldValue.type==='NUMBER' && fieldValue.value!==undefined){
|
||||
return Number(fieldValue.value);
|
||||
}else{
|
||||
return fieldValue.value;
|
||||
}
|
||||
}else if(object.objectType==='variable'){
|
||||
return context.variables[object.name].value;
|
||||
return context.record[object.code].value;
|
||||
}else if(object.objectType==='var'){
|
||||
return context.variables[object.varName].value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,12 +397,6 @@ export class ConditionTree {
|
||||
*/
|
||||
compare(operator: Operator, targetValue: any, value: any): boolean {
|
||||
// targetValue は日期时,value も日期に変換して比較する
|
||||
if(targetValue===undefined || targetValue===null||targetValue===''){
|
||||
if(value===undefined || value===null||value===''){
|
||||
targetValue='';
|
||||
value='';
|
||||
}
|
||||
}
|
||||
if (targetValue instanceof Date) {
|
||||
const dateValue = new Date(value);
|
||||
if (!isNaN(dateValue.getTime())) {
|
||||
|
||||
@@ -3,12 +3,6 @@ import { actionAddins } from "../actions";
|
||||
import '../actions/must-input';
|
||||
import '../actions/auto-numbering';
|
||||
import '../actions/field-shown';
|
||||
import '../actions/error-show';
|
||||
import '../actions/button-add';
|
||||
import '../actions/condition-action';
|
||||
import '../actions/regular-check';
|
||||
import '../actions/mail-check';
|
||||
import '../actions/counter-check';
|
||||
import { ActionFlow,IActionFlow, IActionResult,IContext } from "./ActionTypes";
|
||||
|
||||
export class ActionProcess{
|
||||
@@ -41,11 +35,7 @@ export class ActionProcess{
|
||||
if(action!==undefined){
|
||||
result = await action.process(nextAction,this.event,this.context);
|
||||
}
|
||||
let nextInput = '';
|
||||
//outputPoints一つ以上の場合、次のInputPointは戻り値を設定する
|
||||
if(nextAction.outputPoints && nextAction.outputPoints.length>1){
|
||||
nextInput = result.result||'';
|
||||
}
|
||||
const nextInput = nextAction.outputPoints!==undefined?result.result||'':'';
|
||||
id=nextAction.nextNodeIds.get(nextInput);
|
||||
if(id===undefined) return;
|
||||
nextAction = this.flow.findNodeById(id);
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
|
||||
@@ -221,8 +221,3 @@ vite@^4.4.5:
|
||||
rollup "^3.27.1"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
yarn@^1.22.22:
|
||||
version "1.22.22"
|
||||
resolved "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz"
|
||||
integrity sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==
|
||||
|
||||
144
sample.json
144
sample.json
@@ -1,113 +1,33 @@
|
||||
{
|
||||
"id": "",
|
||||
"actionNodes": [
|
||||
{
|
||||
"id": "c5cd772a-04be-418e-a811-3787f98a2285",
|
||||
"name": "app.record.create.show",
|
||||
"title": "レコード追加画面",
|
||||
"subTitle": "レコード追加画面を表示した後",
|
||||
"inputPoint": "",
|
||||
"outputPoints": [],
|
||||
"isRoot": true,
|
||||
"actionProps": [],
|
||||
"ActionValue": {},
|
||||
"nextNodeIds": {
|
||||
"": "1eb097b1-9d08-462e-97b0-6e3e1232edef"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "1eb097b1-9d08-462e-97b0-6e3e1232edef",
|
||||
"name": "属性UIテスト用",
|
||||
"inputPoint": "",
|
||||
"outputPoints": [],
|
||||
"actionProps": [
|
||||
{
|
||||
"component": "InputText",
|
||||
"props": {
|
||||
"name": "displayName",
|
||||
"displayName": "表示名",
|
||||
"placeholder": "表示を入力してください",
|
||||
"hint": "",
|
||||
"modelValue": "属性UIテスト用"
|
||||
}
|
||||
},
|
||||
{
|
||||
"component": "AppFieldSelect",
|
||||
"props": {
|
||||
"displayName": "フィールド選択(複数)",
|
||||
"modelValue": {
|
||||
"app": {
|
||||
"id": "64",
|
||||
"name": "日報テスト",
|
||||
"description": "日々の業務内容、報告事項、所感などを記載していくアプリです。\n記録を行うだけでなく、あとからの振り返りやメンバー間のコミュニケーションにも活用できます。",
|
||||
"createdate": "2023/07/15 10:15:03"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "ステータス",
|
||||
"type": "STATUS",
|
||||
"code": "ステータス",
|
||||
"label": "ステータス",
|
||||
"enabled": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "selectFields",
|
||||
"placeholder": "アプリ選択後、フィールドを選んでください",
|
||||
"selectType": "multiple"
|
||||
}
|
||||
},
|
||||
{
|
||||
"component": "AppFieldSelect",
|
||||
"props": {
|
||||
"displayName": "フィールド選択(単一)",
|
||||
"modelValue": {
|
||||
"app": {
|
||||
"id": "58",
|
||||
"name": "日報",
|
||||
"description": "",
|
||||
"createdate": "2023/07/13 19:05:26"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "所感、学び",
|
||||
"type": "MULTI_LINE_TEXT",
|
||||
"code": "文字列__複数行__0",
|
||||
"label": "所感、学び",
|
||||
"noLabel": false,
|
||||
"required": false,
|
||||
"defaultValue": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "selectField",
|
||||
"placeholder": "アプリ選択後、フィールドを選んでください",
|
||||
"selectType": "single"
|
||||
}
|
||||
},
|
||||
{
|
||||
"component": "ColorPicker",
|
||||
"props": {
|
||||
"displayName": "色選択",
|
||||
"modelValue": "#f50000",
|
||||
"name": "color",
|
||||
"placeholder": "カラーを選択してください"
|
||||
}
|
||||
},
|
||||
{
|
||||
"component": "NumInput",
|
||||
"props": {
|
||||
"displayName": "数値入力フィールド",
|
||||
"modelValue": 100,
|
||||
"name": "num",
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"placeholder": "数値を入力してください"
|
||||
}
|
||||
}
|
||||
],
|
||||
"prevNodeId": "c5cd772a-04be-418e-a811-3787f98a2285",
|
||||
"nextNodeIds": {}
|
||||
[
|
||||
{
|
||||
"component": "FieldInput",
|
||||
"props": {
|
||||
"displayName": "フィールド",
|
||||
"modelValue": {},
|
||||
"name": "field",
|
||||
"placeholder": "対象項目を選択してください"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"component": "SelectBox",
|
||||
"props": {
|
||||
"displayName": "表示/非表示",
|
||||
"options": [
|
||||
"表示",
|
||||
"非表示"
|
||||
],
|
||||
"modelValue": "",
|
||||
"name": "show",
|
||||
"placeholder": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"component": "ConditionInput",
|
||||
"props": {
|
||||
"displayName": "条件",
|
||||
"modelValue": "",
|
||||
"name": "condition",
|
||||
"placeholder": "対象項目を選択してください"
|
||||
}
|
||||
}
|
||||
]
|
||||
112
sample2.json
112
sample2.json
@@ -1,55 +1,59 @@
|
||||
[
|
||||
{
|
||||
"component": "InputText",
|
||||
"props": {
|
||||
"displayName": "文字入力",
|
||||
"modelValue": "",
|
||||
"name": "str",
|
||||
"placeholder": "文字を入力してください",
|
||||
"maxLength":"20",
|
||||
"hint":"文字列入力<br>入力ルール指定可能。ルールの設定例:[val=>!!val||'必須入力です']",
|
||||
"rules":"[val=>!!val||'必須入力です']"
|
||||
{
|
||||
"index": 0,
|
||||
"type": "root",
|
||||
"children": [
|
||||
{
|
||||
"index": 1,
|
||||
"type": "condition",
|
||||
"parent": "root",
|
||||
"logicalOperator": "AND",
|
||||
"object": {
|
||||
"label": "Field 1",
|
||||
"value": "field1"
|
||||
},
|
||||
"operator": "=",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"index": 2,
|
||||
"type": "condition",
|
||||
"parent": "root",
|
||||
"logicalOperator": "AND",
|
||||
"object": {
|
||||
"label": "Field 1",
|
||||
"value": "field1"
|
||||
},
|
||||
"operator": "=",
|
||||
"value": "2"
|
||||
},
|
||||
{
|
||||
"index": 3,
|
||||
"type": "condition",
|
||||
"parent": "root",
|
||||
"logicalOperator": "AND",
|
||||
"object": {
|
||||
"label": "Field 1",
|
||||
"value": "field1"
|
||||
},
|
||||
"operator": {
|
||||
"label": ">",
|
||||
"value": "Greater"
|
||||
},
|
||||
"value": "3"
|
||||
},
|
||||
{
|
||||
"index": 4,
|
||||
"type": "condition",
|
||||
"parent": "root",
|
||||
"logicalOperator": "AND",
|
||||
"object": {
|
||||
"label": "Field 1",
|
||||
"value": "field1"
|
||||
},
|
||||
"operator": "=",
|
||||
"value": "4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"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の範囲内の数値を入力してください']"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"parent": null,
|
||||
"logicalOperator": "AND"
|
||||
}
|
||||
Reference in New Issue
Block a user