Compare commits
26 Commits
dev3
...
c24a3e5695
| Author | SHA1 | Date | |
|---|---|---|---|
| c24a3e5695 | |||
| 2a290c3142 | |||
| de717f25a5 | |||
| 9c4adc48ba | |||
|
|
171f0dfa89 | ||
|
|
6869505d9a | ||
|
|
a8ec97969f | ||
| c58887942b | |||
| 7fccf97eaf | |||
| e233e08857 | |||
| 85f1a7e569 | |||
| d9fd738a19 | |||
| 5cc2b6111b | |||
| 409db1e111 | |||
| 803d3b05a0 | |||
| 044934ea28 | |||
| 058d402643 | |||
| 179d6e1106 | |||
| 974f90eb2a | |||
| 0f6494acdc | |||
|
|
3c6e4a6faa | ||
|
|
e1b416060f | ||
|
|
a78f403d29 | ||
|
|
47a2fd588e | ||
|
|
3279959bdb | ||
|
|
b68d58fd0f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ backend/pyvenv.cfg
|
|||||||
backend/Include/
|
backend/Include/
|
||||||
backend/Scripts/
|
backend/Scripts/
|
||||||
|
|
||||||
|
log/api.log
|
||||||
|
|||||||
2
backend/.deployment
Normal file
2
backend/.deployment
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[config]
|
||||||
|
SCM_DO_BUILD_DURING_DEPLOYMENT=true
|
||||||
File diff suppressed because one or more lines are too long
@@ -3,6 +3,7 @@ from io import BytesIO
|
|||||||
import typing as t
|
import typing as t
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import json
|
import json
|
||||||
|
import base64
|
||||||
import httpx
|
import httpx
|
||||||
import deepdiff
|
import deepdiff
|
||||||
import app.core.config as config
|
import app.core.config as config
|
||||||
@@ -493,6 +494,17 @@ async def test(file:UploadFile= File(...),app:str=None):
|
|||||||
return test
|
return test
|
||||||
|
|
||||||
|
|
||||||
|
@r.get("/group")
|
||||||
|
async def group(request:Request,kintoneurl:str,kintoneuser:str,kintonepwd:str):
|
||||||
|
try:
|
||||||
|
auth_value = base64.b64encode(bytes(f"{kintoneuser}:{kintonepwd}","utf-8"))
|
||||||
|
headers={config.API_V1_AUTH_KEY:auth_value}
|
||||||
|
url = f"{kintoneurl}/v1/user/groups.json?code={kintoneuser}"
|
||||||
|
r = httpx.get(url,headers=headers)
|
||||||
|
return r.json()
|
||||||
|
except Exception as e:
|
||||||
|
raise APIException('kintone:group',request.url._url, f"Error occurred while get group(url:{kintoneurl} user:{kintoneuser}):",e)
|
||||||
|
|
||||||
@r.post("/download",)
|
@r.post("/download",)
|
||||||
async def download(request:Request,key,c:config.KINTONE_ENV=Depends(getkintoneenv)):
|
async def download(request:Request,key,c:config.KINTONE_ENV=Depends(getkintoneenv)):
|
||||||
try:
|
try:
|
||||||
@@ -502,7 +514,7 @@ async def download(request:Request,key,c:config.KINTONE_ENV=Depends(getkintoneen
|
|||||||
r = httpx.get(url,headers=headers,params=params)
|
r = httpx.get(url,headers=headers,params=params)
|
||||||
return r.json()
|
return r.json()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise APIException('kintone:upload',request.url._url,f"Error occurred while download file.json:",e)
|
raise APIException('kintone:download',request.url._url,f"Error occurred while download file.json:",e)
|
||||||
|
|
||||||
@r.post("/upload")
|
@r.post("/upload")
|
||||||
async def upload(request:Request,files:t.List[UploadFile] = File(...)):
|
async def upload(request:Request,files:t.List[UploadFile] = File(...)):
|
||||||
@@ -625,6 +637,16 @@ async def createapp(request:Request,name:str,env:config.KINTONE_ENV=Depends(getk
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise APIException('kintone:createapp',request.url._url, f"Error occurred while create app({env.DOMAIN_NAME}->{name}):",e)
|
raise APIException('kintone:createapp',request.url._url, f"Error occurred while create app({env.DOMAIN_NAME}->{name}):",e)
|
||||||
|
|
||||||
|
@r.get("/defaultgroup")
|
||||||
|
async def currentgroup(request:Request,env:config.KINTONE_ENV=Depends(getkintoneenv)):
|
||||||
|
try:
|
||||||
|
auth_value = env.API_V1_AUTH_VALUE
|
||||||
|
headers={config.API_V1_AUTH_KEY:auth_value}
|
||||||
|
url = f"{env.BASE_URL}/v1/user/groups.json?code={env.KINTONE_USER}"
|
||||||
|
r = httpx.get(url,headers=headers)
|
||||||
|
return r.json()
|
||||||
|
except Exception as e:
|
||||||
|
raise APIException('kintone:currentgroup',request.url._url, f"Error occurred while get default domain group(domain:{env.DOMAIN_NAME} url:{env.BASE_URL} user:{env.KINTONE_USER}):",e)
|
||||||
|
|
||||||
@r.post("/createappfromexcel",)
|
@r.post("/createappfromexcel",)
|
||||||
async def createappfromexcel(request:Request,files:t.List[UploadFile] = File(...),format:int = 0,env = Depends(getkintoneenv),db = Depends(get_db)):
|
async def createappfromexcel(request:Request,files:t.List[UploadFile] = File(...),format:int = 0,env = Depends(getkintoneenv),db = Depends(get_db)):
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
from urllib.parse import parse_qs, urlencode
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from starlette.middleware.base import BaseHTTPMiddleware
|
from starlette.middleware.base import BaseHTTPMiddleware
|
||||||
@@ -12,6 +13,10 @@ import json
|
|||||||
class LoggingMiddleware(BaseHTTPMiddleware):
|
class LoggingMiddleware(BaseHTTPMiddleware):
|
||||||
async def dispatch(self, request: Request, call_next):
|
async def dispatch(self, request: Request, call_next):
|
||||||
if request.method in ("POST", "PUT", "PATCH","DELETE"):
|
if request.method in ("POST", "PUT", "PATCH","DELETE"):
|
||||||
|
content_type = request.headers.get('content-type', '')
|
||||||
|
if content_type.startswith('multipart/form-data'):
|
||||||
|
request.state.body = None
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
request.state.body = await request.json()
|
request.state.body = await request.json()
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
@@ -34,6 +39,48 @@ class LoggingMiddleware(BaseHTTPMiddleware):
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def sanitize_password(self,data):
|
||||||
|
"""
|
||||||
|
データ内の password パラメータをフィルタリングする機能。
|
||||||
|
dict、JSON 文字列、URL エンコード文字列、QueryDict をサポート。
|
||||||
|
"""
|
||||||
|
if data is None:
|
||||||
|
return data
|
||||||
|
elif isinstance(data, dict):
|
||||||
|
data.pop('password', None)
|
||||||
|
return data
|
||||||
|
elif isinstance(data, list):
|
||||||
|
return [self.sanitize_password(item) for item in data]
|
||||||
|
elif isinstance(data, (str, bytes)):
|
||||||
|
if isinstance(data, bytes):
|
||||||
|
data = data.decode('utf-8') # bytes to str
|
||||||
|
# JSON解析
|
||||||
|
try:
|
||||||
|
parsed_json = json.loads(data)
|
||||||
|
sanitized_json = self.sanitize_password(parsed_json)
|
||||||
|
return json.dumps(sanitized_json, separators=(',', ':'))
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
# URL 解析
|
||||||
|
try:
|
||||||
|
parsed_dict = parse_qs(data)
|
||||||
|
parsed_dict.pop('password', None)
|
||||||
|
return urlencode(parsed_dict, doseq=True)
|
||||||
|
except:
|
||||||
|
parts = data.split('&')
|
||||||
|
filtered_parts = []
|
||||||
|
for part in parts:
|
||||||
|
if '=' in part:
|
||||||
|
key, _ = part.split('=', 1)
|
||||||
|
if key == 'password':
|
||||||
|
continue
|
||||||
|
filtered_parts.append(part)
|
||||||
|
return '&'.join(filtered_parts)
|
||||||
|
# QueryDict 例えば FastAPI の request.query_params)
|
||||||
|
elif hasattr(data, 'items'):
|
||||||
|
return {k: v for k, v in data.items() if k != 'password'}
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
async def log_request(self, request: Request, response,state):
|
async def log_request(self, request: Request, response,state):
|
||||||
try:
|
try:
|
||||||
headers = dict(request.headers)
|
headers = dict(request.headers)
|
||||||
@@ -43,13 +90,24 @@ class LoggingMiddleware(BaseHTTPMiddleware):
|
|||||||
else:
|
else:
|
||||||
path_template = request.url.path
|
path_template = request.url.path
|
||||||
|
|
||||||
db_operation = OperationLog(tenantid =request.state.tenant,
|
# passwordのパラメータを除外する
|
||||||
|
safe_query = self.sanitize_password(request.query_params.items())
|
||||||
|
|
||||||
|
# passwordのパラメータを除外する
|
||||||
|
safe_body = self.sanitize_password(request.state.body)
|
||||||
|
|
||||||
|
db_operation = OperationLog(
|
||||||
|
tenantid =request.state.tenant,
|
||||||
clientip = request.client.host if request.client else None,
|
clientip = request.client.host if request.client else None,
|
||||||
useragent =headers.get("user-agent", ""),
|
useragent =headers.get("user-agent", ""),
|
||||||
userid = request.state.user,
|
userid = request.state.user,
|
||||||
operation = request.method,
|
operation = request.method,
|
||||||
function = path_template,
|
function = path_template,
|
||||||
parameters = str({"path": request.path_params,"query": dict(request.query_params),"body": request.state.body}),
|
parameters = str({
|
||||||
|
"path": request.path_params,
|
||||||
|
"query": safe_query,
|
||||||
|
"body": safe_body
|
||||||
|
}),
|
||||||
response = f"status_code:{response.status_code }" )
|
response = f"status_code:{response.status_code }" )
|
||||||
|
|
||||||
db = request.state.db
|
db = request.state.db
|
||||||
@@ -71,5 +129,3 @@ class LoggingMiddleware(BaseHTTPMiddleware):
|
|||||||
async def write_log_to_db(self, db_operation,db):
|
async def write_log_to_db(self, db_operation,db):
|
||||||
db.add(db_operation)
|
db.add(db_operation)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from fastapi import HTTPException, status
|
from fastapi import HTTPException, status
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
from sqlalchemy.orm.attributes import flag_modified
|
||||||
from sqlalchemy import select,and_
|
from sqlalchemy import select,and_
|
||||||
import typing as t
|
import typing as t
|
||||||
|
|
||||||
@@ -202,6 +203,8 @@ class dbapp(crudbase):
|
|||||||
db_app = self.get_app(db, domainurl, flow.appid)
|
db_app = self.get_app(db, domainurl, flow.appid)
|
||||||
if db_app and db_app.version > 0:
|
if db_app and db_app.version > 0:
|
||||||
db_app.is_saved = True
|
db_app.is_saved = True
|
||||||
|
flag_modified(db_app, 'is_saved')
|
||||||
|
db_app.updateuserid = userid
|
||||||
db.add(db_app)
|
db.add(db_app)
|
||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(db_flow)
|
db.refresh(db_flow)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from app.core.security import chacha20Decrypt
|
|||||||
class Base:
|
class Base:
|
||||||
id = Column(Integer, primary_key=True, index=True)
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
create_time = Column(DateTime, default=datetime.now(timezone.utc))
|
create_time = Column(DateTime, default=datetime.now(timezone.utc))
|
||||||
update_time = Column(DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc))
|
update_time = Column(DateTime, default=datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
|
||||||
|
|
||||||
|
|
||||||
userrole = Table(
|
userrole = Table(
|
||||||
@@ -234,7 +234,7 @@ class OperationLog(Base):
|
|||||||
userid = mapped_column(Integer,ForeignKey("user.id"))
|
userid = mapped_column(Integer,ForeignKey("user.id"))
|
||||||
operation = mapped_column(String(200))
|
operation = mapped_column(String(200))
|
||||||
function = mapped_column(String(200))
|
function = mapped_column(String(200))
|
||||||
parameters = mapped_column(String(200))
|
parameters = mapped_column(String)
|
||||||
response = mapped_column(String(200))
|
response = mapped_column(String(200))
|
||||||
user = relationship('User')
|
user = relationship('User')
|
||||||
|
|
||||||
|
|||||||
7285
db/kintone-dev2-db.sql
Normal file
7285
db/kintone-dev2-db.sql
Normal file
File diff suppressed because one or more lines are too long
BIN
document/Ver2機能一覧 1.xlsx
Normal file
BIN
document/Ver2機能一覧 1.xlsx
Normal file
Binary file not shown.
@@ -1,211 +0,0 @@
|
|||||||
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" version="24.9.2">
|
|
||||||
<diagram name="ページ1" id="oKiyF3b1qzm0IX1SNAWJ">
|
|
||||||
<mxGraphModel dx="1395" dy="1078" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
|
||||||
<root>
|
|
||||||
<mxCell id="0" />
|
|
||||||
<mxCell id="1" parent="0" />
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-73" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d0cee2;strokeColor=#56517e;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="92" y="645" width="720" height="180" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-71" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="110" y="605" width="720" height="180" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-53" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffcccc;strokeColor=#36393d;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="140" y="570" width="720" height="180" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-52" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#cdeb8b;strokeColor=#36393d;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="170" y="530" width="720" height="180" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-51" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ffcc99;strokeColor=#36393d;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="210" y="490" width="720" height="180" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-49" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="90" y="20" width="1080" height="290" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-10" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-1" target="Clf12EPbcqlM1huzJpPN-9">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-1" value="タスク開始" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="120" y="215" width="90" height="50" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-45" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;curved=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-8" target="Clf12EPbcqlM1huzJpPN-9">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-47" value="DBからクロールのタスクを取得する" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="Clf12EPbcqlM1huzJpPN-45">
|
|
||||||
<mxGeometry x="0.2449" y="53" relative="1" as="geometry">
|
|
||||||
<mxPoint x="17" y="-44" as="offset" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-8" target="Clf12EPbcqlM1huzJpPN-78">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-8" value="DB" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#cce5ff;strokeColor=#36393d;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="570" y="-110" width="100" height="70" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-9" value="<div style="background-color: rgb(255, 255, 254); font-family: Consolas, &quot;Courier New&quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;"><span style="">タスクスケジューラ</span></div>" style="whiteSpace=wrap;html=1;rounded=1;fontColor=default;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="260" y="217.5" width="140" height="45" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;curved=1;startArrow=block;startFill=1;endArrow=none;endFill=0;dashed=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-15" target="Clf12EPbcqlM1huzJpPN-9">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-18" value="タスクの割り当て" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="Clf12EPbcqlM1huzJpPN-17">
|
|
||||||
<mxGeometry x="0.04" relative="1" as="geometry">
|
|
||||||
<mxPoint x="-18" y="30" as="offset" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;curved=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-15" target="Clf12EPbcqlM1huzJpPN-31">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-15" value="<b>RabbitMQ</b>" style="whiteSpace=wrap;html=1;rounded=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="510" y="380" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-19" target="Clf12EPbcqlM1huzJpPN-21">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-19" value="MQコマンドの受信" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="250" y="560" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;curved=1;dashed=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-15" target="Clf12EPbcqlM1huzJpPN-19">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-21" target="Clf12EPbcqlM1huzJpPN-23">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-21" value="データ収集" style="whiteSpace=wrap;html=1;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="490" y="560" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;curved=1;dashed=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-23" target="Clf12EPbcqlM1huzJpPN-15">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-23" value="結果をMQメッセージを変換" style="whiteSpace=wrap;html=1;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="740" y="560" width="170" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;curved=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-26" target="Clf12EPbcqlM1huzJpPN-31">
|
|
||||||
<mxGeometry relative="1" as="geometry">
|
|
||||||
<Array as="points">
|
|
||||||
<mxPoint x="980" y="390" />
|
|
||||||
<mxPoint x="980" y="350" />
|
|
||||||
<mxPoint x="745" y="350" />
|
|
||||||
</Array>
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-26" value="データ収集結果<br>一時保存" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#eeeeee;strokeColor=#36393d;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="970" y="390" width="100" height="70" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-27" value="タスクコマンド" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="1">
|
|
||||||
<mxGeometry x="340" y="450" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-23" target="Clf12EPbcqlM1huzJpPN-26">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-29" value="コンテンツなど大きい情報を一時保存" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="950" y="500" width="230" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-30" value="収集結果通知MQ" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="740" y="450" width="110" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-31" target="Clf12EPbcqlM1huzJpPN-36">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-31" value="メッセージキューから<div>データ受信</div>" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="677" y="212.5" width="150" height="50" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-34" value="MQのキーで収集結果を取得" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="760" y="350" width="170" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-39" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-36" target="Clf12EPbcqlM1huzJpPN-38">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-36" value="<div style="background-color: rgb(255, 255, 254); font-family: Consolas, &quot;Courier New&quot;, monospace; line-height: 19px; white-space: pre;"><span>データクリーニング<br>と重複排除</span></div>" style="whiteSpace=wrap;html=1;rounded=1;fontColor=default;fontSize=11;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="890" y="207.5" width="148" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-43" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-38" target="Clf12EPbcqlM1huzJpPN-42">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-38" value="データベースに保存" style="whiteSpace=wrap;html=1;fontSize=11;rounded=1;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="904" y="60" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-42" target="Clf12EPbcqlM1huzJpPN-31">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-42" value="収集結果からサブ項目を抽出" style="whiteSpace=wrap;html=1;fontSize=11;rounded=1;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="692" y="60" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;curved=1;dashed=1;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-38" target="Clf12EPbcqlM1huzJpPN-8">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-48" value="クロール結果をDBに登録する" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="Clf12EPbcqlM1huzJpPN-46">
|
|
||||||
<mxGeometry x="0.1149" y="13" relative="1" as="geometry">
|
|
||||||
<mxPoint as="offset" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-50" value="<b>メインプログラム</b>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="540" y="20" width="130" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-54" value="<b>クローラー サブプログラム</b>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="485" y="490" width="185" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-55" value="<b>SharePointクローラー</b>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="220" y="640" width="130" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-60" value="MQ情報" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;align=center;fontSize=14;fillColor=#dae8fc;strokeColor=#6c8ebf;gradientColor=#7ea6e0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="1024" y="630" width="160" height="236" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-61" value="MQキー" style="text;strokeColor=none;fillColor=none;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="Clf12EPbcqlM1huzJpPN-60">
|
|
||||||
<mxGeometry y="26" width="160" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-70" value="クローラーID" style="text;strokeColor=none;fillColor=none;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="Clf12EPbcqlM1huzJpPN-60">
|
|
||||||
<mxGeometry y="56" width="160" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-62" value="分類" style="text;strokeColor=none;fillColor=none;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="Clf12EPbcqlM1huzJpPN-60">
|
|
||||||
<mxGeometry y="86" width="160" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-63" value="タイトル" style="text;strokeColor=none;fillColor=none;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="Clf12EPbcqlM1huzJpPN-60">
|
|
||||||
<mxGeometry y="116" width="160" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-64" value="URL" style="text;strokeColor=none;fillColor=none;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="Clf12EPbcqlM1huzJpPN-60">
|
|
||||||
<mxGeometry y="146" width="160" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-65" value="サブ項目" style="text;strokeColor=none;fillColor=none;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="Clf12EPbcqlM1huzJpPN-60">
|
|
||||||
<mxGeometry y="176" width="160" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-66" value="コンテンツ" style="text;strokeColor=none;fillColor=none;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;fontSize=12;whiteSpace=wrap;html=1;" vertex="1" parent="Clf12EPbcqlM1huzJpPN-60">
|
|
||||||
<mxGeometry y="206" width="160" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-67" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-60" target="Clf12EPbcqlM1huzJpPN-23">
|
|
||||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
|
||||||
<mxPoint x="930" y="840" as="sourcePoint" />
|
|
||||||
<mxPoint x="980" y="790" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-68" value="<b>OneNodeクローラー</b>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="180" y="680" width="130" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-69" value="<b>EIM クローラー</b>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="150" y="720" width="130" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-72" value="<b>Coredasuクローラー</b>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="120" y="755" width="130" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-74" value="<b>その他クローラー</b>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="92" y="795" width="130" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-75" value="PostGre SQL" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="585" y="-40" width="90" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-76" value="再帰的な処理" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="1030" y="140" width="80" height="50" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-77" value="NEO4J" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="570" y="-390" width="100" height="80" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-78" value="データ抽出" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="560" y="-250" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="Clf12EPbcqlM1huzJpPN-80" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="Clf12EPbcqlM1huzJpPN-78" target="Clf12EPbcqlM1huzJpPN-77">
|
|
||||||
<mxGeometry relative="1" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
</root>
|
|
||||||
</mxGraphModel>
|
|
||||||
</diagram>
|
|
||||||
</mxfile>
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#開発環境
|
#開発環境
|
||||||
#KAB_BACKEND_URL="https://kab-backend.azurewebsites.net/"
|
#KAB_BACKEND_URL="https://ktune-backend-dev-eba8fkeyffegc3cz.japanwest-01.azurewebsites.net/"
|
||||||
#単体テスト環境
|
#単体テスト環境
|
||||||
#KAB_BACKEND_URL="https://kab-backend-unittest.azurewebsites.net/"
|
#KAB_BACKEND_URL="https://kab-backend-unittest.azurewebsites.net/"
|
||||||
#ローカル開発環境
|
#ローカル開発環境
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
indicator-color="primary"
|
indicator-color="primary"
|
||||||
active-bg-color="primary"
|
active-bg-color="primary"
|
||||||
class="bg-grey-2 text-grey-8"
|
class="bg-grey-2 text-grey-8"
|
||||||
|
@update:model-value="() => selected = []"
|
||||||
dense
|
dense
|
||||||
>
|
>
|
||||||
<q-tab :name="cate"
|
<q-tab :name="cate"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ref, PropType } from 'vue';
|
import { ref, PropType, watchEffect } from 'vue';
|
||||||
import { api } from 'boot/axios';
|
import { api } from 'boot/axios';
|
||||||
import DetailFieldTable from './dialog/DetailFieldTable.vue';
|
import DetailFieldTable from './dialog/DetailFieldTable.vue';
|
||||||
|
|
||||||
@@ -33,6 +33,9 @@ export default {
|
|||||||
filter: String,
|
filter: String,
|
||||||
filterInitRowsFunc: {
|
filterInitRowsFunc: {
|
||||||
type: Function as PropType<(app: IAppDisplay) => boolean>,
|
type: Function as PropType<(app: IAppDisplay) => boolean>,
|
||||||
|
},
|
||||||
|
updateSelectApp: {
|
||||||
|
type: Function
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
@@ -44,6 +47,12 @@ export default {
|
|||||||
{ name: 'createdate', label: '作成日時', field: 'createdate', align: 'left' }
|
{ name: 'createdate', label: '作成日時', field: 'createdate', align: 'left' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
watchEffect(()=>{
|
||||||
|
if (selected.value && selected.value[0] && props.updateSelectApp) {
|
||||||
|
props.updateSelectApp(selected.value[0])
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const fetchApps = async () => {
|
const fetchApps = async () => {
|
||||||
const res = await api.get('api/v1/allapps');
|
const res = await api.get('api/v1/allapps');
|
||||||
return res.data.apps.map((item: any) => ({
|
return res.data.apps.map((item: any) => ({
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
input-debounce="0"
|
input-debounce="0"
|
||||||
:options="canSharedUserFilteredOptions"
|
:options="canSharedUserFilteredOptions"
|
||||||
clearable
|
clearable
|
||||||
:placeholder="canSharedUserFilter ? '' : domain.domainActive ? '権限を付与するユーザーを選択' : 'ドメインが無効なため、権限を付与できません'"
|
:placeholder="canSharedUserFilter ? '' : domain.domainActive ? '権限を付与するユーザーを選択' : '接続先が無効なため、権限を付与できません'"
|
||||||
@filter="filterFn">
|
@filter="filterFn">
|
||||||
|
|
||||||
<template v-slot:selected-item="scope">
|
<template v-slot:selected-item="scope">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<share-domain-dialog
|
<share-domain-dialog
|
||||||
:dialogTitle="`「${domain.name}」のドメイン利用権限設定`"
|
:dialogTitle="`「${domain.name}」の接続先利用権限設定`"
|
||||||
userListTitle="ドメイン利用権限を持つユーザー"
|
userListTitle="接続先利用権限を持つユーザー"
|
||||||
:domain="domain"
|
:domain="domain"
|
||||||
:share-api="shareApi"
|
:share-api="shareApi"
|
||||||
:remove-shared-api="removeSharedApi"
|
:remove-shared-api="removeSharedApi"
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ const essentialLinks: EssentialLinkProps[] = reactive([
|
|||||||
target: '_self',
|
target: '_self',
|
||||||
permission: MenuMapping.role
|
permission: MenuMapping.role
|
||||||
},
|
},
|
||||||
// ------------ドメイン-------------
|
// ------------接続先管理-------------
|
||||||
{
|
{
|
||||||
title: '接続先管理',
|
title: '接続先管理',
|
||||||
caption: 'kintoneの接続先設定',
|
caption: 'kintoneの接続先設定',
|
||||||
|
|||||||
@@ -232,8 +232,38 @@ const onDeploy = async () => {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
deployLoading.value = true;
|
deployLoading.value = true;
|
||||||
|
try {
|
||||||
|
const { data }: {data: {code: string, groups: {code: string}[]}} = await api.get('api/v1/defaultgroup');
|
||||||
|
if (data.code === 'CB_WA01') {
|
||||||
|
$q.notify({
|
||||||
|
type: 'negative',
|
||||||
|
caption: 'エラー',
|
||||||
|
message: 'ユーザーのパスワード認証に失敗しました。'
|
||||||
|
});
|
||||||
|
deployLoading.value = false;
|
||||||
|
return;
|
||||||
|
} else if (!data.groups || !data.groups.some((group: {code: string}) => group.code === 'Administrators')){
|
||||||
|
$q.notify({
|
||||||
|
type: 'negative',
|
||||||
|
caption: 'エラー',
|
||||||
|
message: 'この操作には管理者権限が必要です。'
|
||||||
|
});
|
||||||
|
deployLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
$q.notify({
|
||||||
|
type: 'negative',
|
||||||
|
caption: 'エラー',
|
||||||
|
message: 'サーバーに接続できませんでした。'
|
||||||
|
});
|
||||||
|
deployLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
await store.deploy();
|
await store.deploy();
|
||||||
deployLoading.value = false;
|
deployLoading.value = false;
|
||||||
$q.notify({
|
$q.notify({
|
||||||
|
|||||||
@@ -53,21 +53,21 @@
|
|||||||
<div class="text-h6 q-ma-sm">Kintone Account</div>
|
<div class="text-h6 q-ma-sm">Kintone Account</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<q-card-section class="q-pt-none q-mt-none">
|
<q-card-section class="q-py-none q-mt-none">
|
||||||
<div class="q-gutter-lg">
|
<div class="q-gutter-lg">
|
||||||
|
|
||||||
<q-input filled v-model="name" label="環境名 *" hint="kintoneの環境名を入力してください" lazy-rules
|
<q-input filled v-model="name" label="環境名 *" hint="kintoneの環境名を入力してください" lazy-rules
|
||||||
:rules="[val => val && val.length > 0 || 'kintoneの環境名を入力してください。']" />
|
:rules="[val => val && val.length > 0 || 'kintoneの環境名を入力してください。']" />
|
||||||
|
|
||||||
<q-input filled type="url" v-model.trim="url" label="Kintone url" hint="KintoneのURLを入力してください" lazy-rules
|
<q-input filled v-model.trim="url" :readonly="!isCreate" label="Kintone url" :hint="isCreate ? 'KintoneのURLを入力してください':'KintoneのURLは変更できません。新規作成してください。'" lazy-rules
|
||||||
:rules="[val => val && val.length > 0 || 'KintoneのURLを入力してください']" />
|
:rules="[val => val && val.length > 0 || 'KintoneのURLを入力してください']" />
|
||||||
|
|
||||||
<q-input filled v-model="kintoneuser" label="ログイン名 *" hint="Kintoneのログイン名を入力してください" lazy-rules
|
<q-input v-if="isCreate" filled v-model="kintoneuser" label="ログイン名 *" hint="Kintoneのログイン名を入力してください" lazy-rules
|
||||||
:rules="[val => val && val.length > 0 || 'Kintoneのログイン名を入力してください']" autocomplete="new-password" />
|
:rules="[val => val && val.length > 0 || 'Kintoneのログイン名を入力してください']" autocomplete="new-password" />
|
||||||
|
|
||||||
<q-input v-if="isCreate" v-model="kintonepwd" filled :type="isPwd ? 'password' : 'text'"
|
<q-input v-if="isCreate" v-model="kintonepwd" filled :type="isPwd ? 'password' : 'text'"
|
||||||
hint="パスワード" label="パスワード" :disable="!isCreate" lazy-rules
|
hint="Kintoneのパスワードを入力してください" label="パスワード" :disable="!isCreate" lazy-rules
|
||||||
:rules="[val => val && val.length > 0 || 'Please type something']" autocomplete="new-password">
|
:rules="[val => val && val.length > 0 || 'Kintoneのパスワードを入力してください']" autocomplete="new-password">
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
||||||
@click="isPwd = !isPwd" />
|
@click="isPwd = !isPwd" />
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
<q-item tag="label" class="q-pl-sm q-pr-none q-py-xs">
|
<q-item tag="label" class="q-pl-sm q-pr-none q-py-xs">
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>ドメインの有効化</q-item-label>
|
<q-item-label>接続先の有効化</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section avatar>
|
<q-item-section avatar>
|
||||||
<q-toggle v-model="domainActive" />
|
<q-toggle v-model="domainActive" />
|
||||||
@@ -88,30 +88,51 @@
|
|||||||
|
|
||||||
<q-item tag="label" class="q-pl-sm q-pr-none q-py-xs">
|
<q-item tag="label" class="q-pl-sm q-pr-none q-py-xs">
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>パスワードリセット</q-item-label>
|
<q-item-label>管理者アカウントの変更</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section avatar>
|
<q-item-section avatar>
|
||||||
<q-toggle v-model="resetPsw" @update:model-value="updateResetPsw" />
|
<q-toggle v-model="changeAccount" @update:model-value="updateChangeAccount" />
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
||||||
<q-input v-model="kintonepwd" filled :type="isPwd ? 'password' : 'text'" hint="パスワードを入力してください"
|
<q-expansion-item
|
||||||
label="パスワード" :disable="!resetPsw" lazy-rules
|
header-class="hidden"
|
||||||
:rules="[val => val && val.length > 0 || 'Please type something']" autocomplete="new-password">
|
class="q-mt-none"
|
||||||
|
v-model="changeAccount"
|
||||||
|
>
|
||||||
|
<q-input filled v-model="kintoneuser" label="ログイン名 *" hint="Kintoneのログイン名を入力してください" :disable="!changeAccount"
|
||||||
|
:rules="[val => val && val.length > 0 || 'Kintoneのログイン名を入力してください']" lazy-rules class="q-mt-md"/>
|
||||||
|
|
||||||
|
<q-input v-model="kintonepwd" filled :type="isPwd ? 'password' : 'text'" hint="Kintoneのパスワードを入力してください"
|
||||||
|
label="パスワード" :disable="!changeAccount" lazy-rules class="q-mt-lg q-mb-md"
|
||||||
|
:rules="[val => val && val.length > 0 || 'Kintoneのパスワードを入力してください']" autocomplete="new-password">
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
||||||
@click="isPwd = !isPwd" />
|
@click="isPwd = !isPwd" />
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
<!-- <q-btn label="asdf"/> -->
|
<!-- <q-btn label="asdf"/> -->
|
||||||
|
</q-expansion-item>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions align="right" class="text-primary q-mb-md q-mx-sm">
|
|
||||||
<q-btn :loading="addEditLoading" label="保存" type="submit" color="primary" />
|
<div class="q-mt-none">
|
||||||
|
<q-banner dense :class="['text-white q-mt-sm q-py-xs q-mx-md', testResult?.success ? 'bg-green':'bg-red', testResult?.msg ? '':'invisible']">
|
||||||
|
{{ testResult?.msg }}
|
||||||
|
</q-banner>
|
||||||
|
<q-card-actions class="text-primary q-mb-md q-mx-sm relative-position">
|
||||||
|
<q-btn v-if="isCreate || changeAccount" :disable="!isConnectable" :loading="!!connectLoading" padding="xs md" :label="!!connectLoading ? '確認中...' : '接続確認'"
|
||||||
|
color="primary" outline @click="tryConnect()"/>
|
||||||
|
<q-btn v-if="!!connectLoading" label="停止" color="negative" flat class="q-ml-sm" @click="stopConnect" />
|
||||||
|
<q-space />
|
||||||
|
<q-btn :loading="addEditLoading" padding="xs md" label="保存" type="submit" color="primary" />
|
||||||
<q-btn label="キャンセル" type="cancel" color="primary" flat class="q-ml-sm" @click="closeDg()" />
|
<q-btn label="キャンセル" type="cancel" color="primary" flat class="q-ml-sm" @click="closeDg()" />
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
|
</div>
|
||||||
</q-form>
|
</q-form>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
|
||||||
@@ -122,12 +143,12 @@
|
|||||||
<!-- -1 loading -->
|
<!-- -1 loading -->
|
||||||
<q-card-section v-if="deleteLoadingState == -1" class="row items-center">
|
<q-card-section v-if="deleteLoadingState == -1" class="row items-center">
|
||||||
<q-spinner color="primary" size="2em"/>
|
<q-spinner color="primary" size="2em"/>
|
||||||
<span class="q-ml-sm">ドメイン利用権限を確認中</span>
|
<span class="q-ml-sm">接続先利用権限を確認中</span>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<!-- > 0 can't delete -->
|
<!-- > 0 can't delete -->
|
||||||
<q-card-section v-else-if="deleteLoadingState > 0" class="row items-center">
|
<q-card-section v-else-if="deleteLoadingState > 0" class="row items-center">
|
||||||
<q-icon name="error" color="negative" size="2em" />
|
<q-icon name="error" color="negative" size="2em" />
|
||||||
<span class="q-ml-sm">ドメインは使用中です。削除してもよろしいですか?</span>
|
<span class="q-ml-sm">接続先は使用中です。削除してもよろしいですか?</span>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<!-- 0/-2 can delete -->
|
<!-- 0/-2 can delete -->
|
||||||
<q-card-section v-else class="row items-center">
|
<q-card-section v-else class="row items-center">
|
||||||
@@ -187,12 +208,14 @@ const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 });
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const addEditLoading = ref(false);
|
const addEditLoading = ref(false);
|
||||||
const deleteLoadingState = ref<number>(-1); // -2: deleteLoading, -1: loading, 0: allow, > 0: user count
|
const deleteLoadingState = ref<number>(-1); // -2: deleteLoading, -1: loading, 0: allow, > 0: user count
|
||||||
|
const connectLoading = ref<AbortController|null>(null);
|
||||||
|
|
||||||
const filter = ref('');
|
const filter = ref('');
|
||||||
const rows = ref<IDomainOwnerDisplay[]>([]);
|
const rows = ref<IDomainOwnerDisplay[]>([]);
|
||||||
const show = ref(false);
|
const show = ref(false);
|
||||||
const confirm = ref(false);
|
const confirm = ref(false);
|
||||||
const resetPsw = ref(false);
|
const changeAccount = ref(false);
|
||||||
|
const testResult = ref<{msg: string, success?: boolean}|null>(null);
|
||||||
|
|
||||||
const currentDomainId = computed(() => authStore.currentDomain.id);
|
const currentDomainId = computed(() => authStore.currentDomain.id);
|
||||||
// const tenantid = ref(authStore.currentDomain.id);
|
// const tenantid = ref(authStore.currentDomain.id);
|
||||||
@@ -200,8 +223,8 @@ const name = ref('');
|
|||||||
const url = ref('');
|
const url = ref('');
|
||||||
const isPwd = ref(true);
|
const isPwd = ref(true);
|
||||||
const kintoneuser = ref('');
|
const kintoneuser = ref('');
|
||||||
|
const kintoneuserBK = ref('');
|
||||||
const kintonepwd = ref('');
|
const kintonepwd = ref('');
|
||||||
const kintonepwdBK = ref('');
|
|
||||||
const domainActive = ref(true);
|
const domainActive = ref(true);
|
||||||
const isCreate = ref(true);
|
const isCreate = ref(true);
|
||||||
let editId = ref(0);
|
let editId = ref(0);
|
||||||
@@ -239,7 +262,7 @@ const actionList = [
|
|||||||
action: (row: IDomainOwnerDisplay) => {openShareDg(SHARE_USE, row)} },
|
action: (row: IDomainOwnerDisplay) => {openShareDg(SHARE_USE, row)} },
|
||||||
{ label: '管理権限設定', icon: 'add_moderator', permission: Actions.domain.grantManage,
|
{ label: '管理権限設定', icon: 'add_moderator', permission: Actions.domain.grantManage,
|
||||||
disable: (row: IDomainOwnerDisplay) => !isOwner(row),
|
disable: (row: IDomainOwnerDisplay) => !isOwner(row),
|
||||||
tooltip: (row: IDomainOwnerDisplay) => isOwner(row) ? '' : 'ドメイン所有者でないため、操作できません',
|
tooltip: (row: IDomainOwnerDisplay) => isOwner(row) ? '' : '接続先の所有者でないため、操作できません',
|
||||||
action: (row: IDomainOwnerDisplay) => {openShareDg(SHARE_MANAGE, row)}
|
action: (row: IDomainOwnerDisplay) => {openShareDg(SHARE_MANAGE, row)}
|
||||||
},
|
},
|
||||||
{ separator: true },
|
{ separator: true },
|
||||||
@@ -316,19 +339,20 @@ function editRow(row: any) {
|
|||||||
name.value = row.name;
|
name.value = row.name;
|
||||||
url.value = row.url;
|
url.value = row.url;
|
||||||
kintoneuser.value = row.user;
|
kintoneuser.value = row.user;
|
||||||
kintonepwd.value = row.password;
|
kintoneuserBK.value = row.user;
|
||||||
|
kintonepwd.value = ''
|
||||||
domainActive.value = row.domainActive;
|
domainActive.value = row.domainActive;
|
||||||
isPwd.value = true;
|
isPwd.value = true;
|
||||||
show.value = true;
|
show.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateResetPsw = (value: boolean) => {
|
const updateChangeAccount = () => {
|
||||||
if (value === true) {
|
kintoneuser.value = kintoneuserBK.value;
|
||||||
kintonepwd.value = ''
|
kintonepwd.value = ''
|
||||||
|
connectLoading.value = null
|
||||||
isPwd.value = true
|
isPwd.value = true
|
||||||
} else {
|
stopConnect();
|
||||||
kintonepwd.value = kintonepwdBK.value
|
testResult.value = null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeDg = () => {
|
const closeDg = () => {
|
||||||
@@ -336,8 +360,61 @@ const closeDg = () => {
|
|||||||
onReset();
|
onReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSubmit = () => {
|
const tryConnect = async (isTest = true) => {
|
||||||
|
testResult.value = null;
|
||||||
|
if (isTest) {
|
||||||
|
connectLoading.value = new AbortController();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const { data }: {data: {code: string, groups: {code: string}[]}} = await api.get('api/v1/group', {
|
||||||
|
params:{
|
||||||
|
kintoneurl: ensureHttps(url.value),
|
||||||
|
kintoneuser: kintoneuser.value,
|
||||||
|
kintonepwd: kintonepwd.value,
|
||||||
|
},
|
||||||
|
signal: (isTest && connectLoading.value) ? connectLoading.value.signal : undefined
|
||||||
|
});
|
||||||
|
if (data.code === 'CB_WA01') {
|
||||||
|
testResult.value = { msg: 'ユーザーのパスワード認証に失敗しました。' }
|
||||||
|
} else if (data.groups && data.groups.some((group: {code: string}) => group.code === 'Administrators')){
|
||||||
|
testResult.value = { success: true, msg: isTest ? 'kintoneの管理者アカウントで接続に成功しました。' : '' }
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
testResult.value = { msg: 'このアカウントはkintoneの管理者アカウントではありません。' }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
const error = e as { code?: string };
|
||||||
|
if (error.code === 'ERR_CANCELED') {
|
||||||
|
console.log('Aborted');
|
||||||
|
} else {
|
||||||
|
testResult.value = { msg: 'サーバーに接続できませんでした。' }
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
connectLoading.value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ensureHttps = (url: string) => {
|
||||||
|
return !/^https?:\/\//i.test(url) ? 'https://' + url : url;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stopConnect = () => {
|
||||||
|
if (!connectLoading.value) return;
|
||||||
|
connectLoading.value?.abort();
|
||||||
|
connectLoading.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
addEditLoading.value = true;
|
addEditLoading.value = true;
|
||||||
|
try {
|
||||||
|
await tryConnect(false);
|
||||||
|
} catch (e) {
|
||||||
|
addEditLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
const method = editId.value !== 0 ? 'put' : 'post';
|
const method = editId.value !== 0 ? 'put' : 'post';
|
||||||
const param: IDomainSubmit = {
|
const param: IDomainSubmit = {
|
||||||
'id': editId.value,
|
'id': editId.value,
|
||||||
@@ -345,7 +422,7 @@ const onSubmit = () => {
|
|||||||
'name': name.value,
|
'name': name.value,
|
||||||
'url': url.value,
|
'url': url.value,
|
||||||
'kintoneuser': kintoneuser.value,
|
'kintoneuser': kintoneuser.value,
|
||||||
'kintonepwd': ((isCreate.value && editId.value == 0) || resetPsw.value) ? kintonepwd.value : '',
|
'kintonepwd': ((isCreate.value && editId.value == 0) || changeAccount.value) ? kintonepwd.value : '',
|
||||||
'is_active': domainActive.value,
|
'is_active': domainActive.value,
|
||||||
'ownerid': authStore.userId || ''
|
'ownerid': authStore.userId || ''
|
||||||
}
|
}
|
||||||
@@ -374,17 +451,24 @@ function openShareDg(type: typeof SHARE_MANAGE|typeof SHARE_USE, row: IDomainOwn
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isConnectable = computed(()=> {
|
||||||
|
return url.value && kintoneuser.value && kintonepwd.value
|
||||||
|
})
|
||||||
|
|
||||||
const onReset = () => {
|
const onReset = () => {
|
||||||
name.value = '';
|
name.value = '';
|
||||||
url.value = '';
|
url.value = '';
|
||||||
kintoneuser.value = '';
|
kintoneuser.value = '';
|
||||||
|
kintoneuserBK.value = '';
|
||||||
kintonepwd.value = '';
|
kintonepwd.value = '';
|
||||||
isPwd.value = true;
|
isPwd.value = true;
|
||||||
editId.value = 0;
|
editId.value = 0;
|
||||||
isCreate.value = true;
|
isCreate.value = true;
|
||||||
domainActive.value = true;
|
domainActive.value = true;
|
||||||
resetPsw.value = false
|
changeAccount.value = false;
|
||||||
addEditLoading.value = false;
|
addEditLoading.value = false;
|
||||||
|
connectLoading.value = null
|
||||||
|
testResult.value = null;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -80,14 +80,14 @@
|
|||||||
|
|
||||||
<q-input v-if="isCreate" v-model="pwd" filled :type="isPwd ? 'password' : 'text'" hint="パスワード"
|
<q-input v-if="isCreate" v-model="pwd" filled :type="isPwd ? 'password' : 'text'" hint="パスワード"
|
||||||
label="パスワード" :disable="!isCreate" lazy-rules
|
label="パスワード" :disable="!isCreate" lazy-rules
|
||||||
:rules="[val => val && val.length > 0 || 'Please type something']" autocomplete="new-password">
|
:rules="[val => val && val.length > 0 || 'パスワードを入力してください']" autocomplete="new-password">
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
||||||
@click="isPwd = !isPwd" />
|
@click="isPwd = !isPwd" />
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
<q-item tag="label" class="q-pl-sm q-pr-none q-py-xs">
|
<q-item tag="label" v-if="authStore.isSuperAdmin" class="q-pl-sm q-pr-none q-py-xs">
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>システム管理者</q-item-label>
|
<q-item-label>システム管理者</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
</q-item>
|
</q-item>
|
||||||
|
|
||||||
<q-input v-model="pwd" filled :type="isPwd ? 'password' : 'text'" hint="パスワードを入力してください" label="パスワード"
|
<q-input v-model="pwd" filled :type="isPwd ? 'password' : 'text'" hint="パスワードを入力してください" label="パスワード"
|
||||||
:disable="!resetPsw" lazy-rules :rules="[val => val && val.length > 0 || 'Please type something']"
|
:disable="!resetPsw" lazy-rules :rules="[val => val && val.length > 0 || 'パスワードを入力してください']"
|
||||||
autocomplete="new-password">
|
autocomplete="new-password">
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions align="right" class="text-primary q-mb-md q-mx-sm">
|
<q-card-actions align="right" class="text-primary q-mb-md q-mx-sm">
|
||||||
<q-btn :loading="addEditLoading" label="保存" type="submit" color="primary" />
|
<q-btn :loading="addEditLoading" padding="xs md" label="保存" type="submit" color="primary" />
|
||||||
<q-btn label="キャンセル" type="cancel" color="primary" flat class="q-ml-sm" @click="closeDg()" />
|
<q-btn label="キャンセル" type="cancel" color="primary" flat class="q-ml-sm" @click="closeDg()" />
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-form>
|
</q-form>
|
||||||
@@ -160,10 +160,12 @@
|
|||||||
import { ref, onMounted, computed } from 'vue';
|
import { ref, onMounted, computed } from 'vue';
|
||||||
import TableActionMenu from 'components/TableActionMenu.vue';
|
import TableActionMenu from 'components/TableActionMenu.vue';
|
||||||
import { useUserStore } from 'stores/useUserStore';
|
import { useUserStore } from 'stores/useUserStore';
|
||||||
|
import { useAuthStore } from 'stores/useAuthStore';
|
||||||
import { IUserDisplay, IUserRolesDisplay } from 'src/types/UserTypes';
|
import { IUserDisplay, IUserRolesDisplay } from 'src/types/UserTypes';
|
||||||
import { Actions } from 'boot/permissions';
|
import { Actions } from 'boot/permissions';
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true },
|
{ name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true },
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export default route(function (/* { store, ssrContext } */) {
|
|||||||
if (!authStore.hasDomain && !domainPages.includes(to.path)) {
|
if (!authStore.hasDomain && !domainPages.includes(to.path)) {
|
||||||
Dialog.create({
|
Dialog.create({
|
||||||
title: '注意',
|
title: '注意',
|
||||||
message: '既定/利用可能なドメインはありません。<br>接続先管理ページに遷移して処理します。',
|
message: '既定/利用可能な接続先はありません。<br>接続先管理ページに遷移して処理します。',
|
||||||
html: true,
|
html: true,
|
||||||
persistent: true,
|
persistent: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export class AutoLookUpAction implements IAction {
|
|||||||
this.actionProps = actionNode.actionProps;
|
this.actionProps = actionNode.actionProps;
|
||||||
this.props = {
|
this.props = {
|
||||||
...actionNode.ActionValue,
|
...actionNode.ActionValue,
|
||||||
condition: JSON.parse((actionNode.ActionValue as any).condition),
|
condition: JSON.parse((actionNode.ActionValue as any).condition || '{}'),
|
||||||
} as IAutoLookUpProps;
|
} as IAutoLookUpProps;
|
||||||
// console.log(context);
|
// console.log(context);
|
||||||
|
|
||||||
@@ -111,7 +111,6 @@ export class AutoLookUpAction implements IAction {
|
|||||||
canNext: true,
|
canNext: true,
|
||||||
result: "",
|
result: "",
|
||||||
} as IActionResult;
|
} as IActionResult;
|
||||||
try {
|
|
||||||
const lookUpFields = this.props.lookupField.fields.filter(
|
const lookUpFields = this.props.lookupField.fields.filter(
|
||||||
(f) => f.lookup && f.lookup.relatedApp.app === String(kintone.app.getId())
|
(f) => f.lookup && f.lookup.relatedApp.app === String(kintone.app.getId())
|
||||||
);
|
);
|
||||||
@@ -120,7 +119,9 @@ export class AutoLookUpAction implements IAction {
|
|||||||
`ルックアップの設定は不正です。${this.props.lookupField.fields[0].label} `
|
`ルックアップの設定は不正です。${this.props.lookupField.fields[0].label} `
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
const lookUpField = this.props.lookupField.fields[0];
|
const lookUpField = this.props.lookupField.fields[0];
|
||||||
|
this.showSpinnerModel(this.props.lookupField.app, lookUpField);
|
||||||
const key = event.record[lookUpField.lookup.relatedKeyField].value;
|
const key = event.record[lookUpField.lookup.relatedKeyField].value;
|
||||||
const targetRecords = await this.getUpdateRecords(lookUpField, key);
|
const targetRecords = await this.getUpdateRecords(lookUpField, key);
|
||||||
//更新対象がない時にスキップ
|
//更新対象がない時にスキップ
|
||||||
@@ -129,7 +130,6 @@ export class AutoLookUpAction implements IAction {
|
|||||||
}
|
}
|
||||||
const updateRecords = this.convertForLookup(targetRecords,lookUpField,key);
|
const updateRecords = this.convertForLookup(targetRecords,lookUpField,key);
|
||||||
console.log("updateRecords", updateRecords);
|
console.log("updateRecords", updateRecords);
|
||||||
this.showSpinnerModel(this.props.lookupField.app,lookUpField);
|
|
||||||
const updateResult = await this.updateLookupTarget(updateRecords);
|
const updateResult = await this.updateLookupTarget(updateRecords);
|
||||||
if(updateResult){
|
if(updateResult){
|
||||||
this.showResult(this.props.lookupField.app,lookUpField,updateRecords.length);
|
this.showResult(this.props.lookupField.app,lookUpField,updateRecords.length);
|
||||||
@@ -157,7 +157,7 @@ export class AutoLookUpAction implements IAction {
|
|||||||
if(typeof key==='string'){
|
if(typeof key==='string'){
|
||||||
query = `${lookUpField.code} = "${key}"`
|
query = `${lookUpField.code} = "${key}"`
|
||||||
}
|
}
|
||||||
if(this.props.condition.queryString!==''){
|
if(!!this.props.condition.queryString){
|
||||||
query = `${query} and (${this.props.condition.queryString})`
|
query = `${query} and (${this.props.condition.queryString})`
|
||||||
}
|
}
|
||||||
return query;
|
return query;
|
||||||
|
|||||||
@@ -645,7 +645,7 @@ export class InsertValueAction implements IAction{
|
|||||||
|
|
||||||
const conditionResult = this.getConditionResult(context);
|
const conditionResult = this.getConditionResult(context);
|
||||||
//保存成功イベントの場合、kintone async/await による非同期処理でフィールドに値を挿入する
|
//保存成功イベントの場合、kintone async/await による非同期処理でフィールドに値を挿入する
|
||||||
if(!event.type.includes('success')){
|
if(!event.type?.includes('success')){
|
||||||
|
|
||||||
//条件式の結果がtrueかつ挿入する値が変換できた場合、フィールド(ラジオボタン・ドロップダウン・チェックボックス・複数選択・文字列一行・文字列複数行・リッチエディタ・数値・日付・日時・時刻)にセット
|
//条件式の結果がtrueかつ挿入する値が変換できた場合、フィールド(ラジオボタン・ドロップダウン・チェックボックス・複数選択・文字列一行・文字列複数行・リッチエディタ・数値・日付・日時・時刻)にセット
|
||||||
if(conditionResult){
|
if(conditionResult){
|
||||||
|
|||||||
52
scripts/kintoneToolDB_20250516_update.sql
Normal file
52
scripts/kintoneToolDB_20250516_update.sql
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
SET statement_timeout = 0;
|
||||||
|
SET lock_timeout = 0;
|
||||||
|
SET idle_in_transaction_session_timeout = 0;
|
||||||
|
SET client_encoding = 'UTF8';
|
||||||
|
SET standard_conforming_strings = on;
|
||||||
|
SELECT pg_catalog.set_config('search_path', '', false);
|
||||||
|
SET check_function_bodies = false;
|
||||||
|
SET xmloption = content;
|
||||||
|
SET client_min_messages = warning;
|
||||||
|
SET row_security = off;
|
||||||
|
|
||||||
|
-- event テーブルに欠落している app.record.index.delete.submit を追加します。
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
max_id INTEGER;
|
||||||
|
BEGIN
|
||||||
|
SELECT MAX(id) INTO max_id FROM public."event";
|
||||||
|
PERFORM pg_catalog.setval('public.event_id_seq', max_id, true);
|
||||||
|
|
||||||
|
INSERT INTO public."event" (create_time, update_time, category, "type", eventid, "function", mobile)
|
||||||
|
VALUES(NOW(), NOW(), 'Kintone', 'レコード一覧画面', 'app.record.index.delete.submit', 'レコードを削除するとき', true)
|
||||||
|
ON CONFLICT (eventid) DO NOTHING;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
|
||||||
|
-- eventaction テーブル
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
max_id INTEGER;
|
||||||
|
BEGIN
|
||||||
|
-- constraint: unique_eventid_actionid
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM pg_constraint
|
||||||
|
WHERE conrelid = 'public.eventaction'::regclass
|
||||||
|
AND conname = 'unique_eventid_actionid'
|
||||||
|
) THEN
|
||||||
|
ALTER TABLE public.eventaction
|
||||||
|
ADD CONSTRAINT unique_eventid_actionid UNIQUE (eventid, actionid);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT MAX(id) INTO max_id FROM public.eventaction;
|
||||||
|
PERFORM pg_catalog.setval('public.eventaction_id_seq', max_id, true);
|
||||||
|
|
||||||
|
-- /must-input.ts
|
||||||
|
INSERT INTO public.eventaction (create_time, update_time, eventid, actionid)
|
||||||
|
VALUES(NOW(), NOW(), 'app.record.detail.delete.submit', 1)
|
||||||
|
, (NOW(), NOW(), 'app.record.index.delete.submit', 1)
|
||||||
|
ON CONFLICT (eventid, actionid) DO NOTHING;
|
||||||
|
|
||||||
|
END $$;
|
||||||
|
|
||||||
Reference in New Issue
Block a user