Compare commits

...

17 Commits

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

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

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

Related work items: #241, #316, #344
2024-06-11 10:32:54 +00:00
14 changed files with 135 additions and 41 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -63,7 +63,7 @@ export default {
Object.keys(fields).forEach((key) => { Object.keys(fields).forEach((key) => {
const fld = fields[key]; const fld = fields[key];
if(props.fieldTypes.length===0 || props.fieldTypes.includes(fld.type)){ if(props.fieldTypes.length===0 || props.fieldTypes.includes(fld.type)){
rows.push({ name: fld.code, ...fld }); rows.push({ name: fld.label || fld.code, ...fld });
} }
}); });
isLoaded.value = true; isLoaded.value = true;

View File

@@ -1,6 +1,6 @@
import { actionAddins } from "."; import { actionAddins } from ".";
import { IField, IAction,IActionResult, IActionNode, IActionProperty, IContext } from "../types/ActionTypes"; import { IField, IAction,IActionResult, IActionNode, IActionProperty, IContext, IVarName } from "../types/ActionTypes";
import { Formatter } from "../util/format"; import { Formatter } from "../util/format";
declare global { declare global {
@@ -13,7 +13,7 @@ interface IAutoNumberingProps{
format:string; format:string;
prefix:string; prefix:string;
suffix:string; suffix:string;
verName:string; verName:IVarName;
} }
export class AutoNumbering implements IAction{ export class AutoNumbering implements IAction{
@@ -29,7 +29,7 @@ export class AutoNumbering implements IAction{
format:'', format:'',
prefix:'', prefix:'',
suffix:'', suffix:'',
verName:'' verName:{name:''}
} }
globalThis.window.$format=this.format; globalThis.window.$format=this.format;
this.register(); this.register();
@@ -56,8 +56,8 @@ export class AutoNumbering implements IAction{
const docNum = await this.createNumber(this.props); const docNum = await this.createNumber(this.props);
record[this.props.field.code].value=docNum; record[this.props.field.code].value=docNum;
//変数設定 //変数設定
if(this.props.verName){ if(this.props.verName && this.props.verName.name!==''){
context.variables[this.props.verName]=docNum; context.variables[this.props.verName.name]=docNum;
} }
result= { result= {
canNext:true, canNext:true,

View File

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

View File

@@ -1,11 +1,11 @@
import { actionAddins } from "."; import { actionAddins } from ".";
import { IAction, IActionResult, IActionNode, IActionProperty, IField ,IContext} from "../types/ActionTypes"; import { IAction, IActionResult, IActionNode, IActionProperty, IField ,IContext, IVarName} from "../types/ActionTypes";
/** /**
* アクションの属性定義 * アクションの属性定義
*/ */
interface IDatetimeGetterProps { interface IDatetimeGetterProps {
/**変数の名前 */ /**変数の名前 */
verName:string; verName:IVarName;
} }
/** /**
* 現在日時を取得するアクション * 現在日時を取得するアクション
@@ -18,7 +18,7 @@ export class DatetimeGetterAction implements IAction {
this.name = "現在日時"; this.name = "現在日時";
this.actionProps = []; this.actionProps = [];
this.props = { this.props = {
verName:'' verName:{name:''}
} }
this.register(); this.register();
} }
@@ -45,8 +45,8 @@ export class DatetimeGetterAction implements IAction {
let today = new Date(); let today = new Date();
if(this.props.verName){ if(this.props.verName && this.props.verName.name!==''){
context.variables[this.props.verName]=today.toISOString(); context.variables[this.props.verName.name]=today.toISOString();
} }
return result; return result;

View File

@@ -44,7 +44,7 @@ export class StringJoinAction implements IAction{
* @param context コンテキスト(レコード、変数情報を持っている) * @param context コンテキスト(レコード、変数情報を持っている)
* @returns * @returns
*/ */
  //非同期処理ある関数下のある属性: //非同期処理ある関数下のある属性:
async process(actionNode:IActionNode,event:any):Promise<IActionResult> { async process(actionNode:IActionNode,event:any):Promise<IActionResult> {
let result={ let result={
//後継処理不可: //後継処理不可:
@@ -107,7 +107,7 @@ export class StringJoinAction implements IAction{
for(let i=0;i<mototext.length;i++){ for(let i=0;i<mototext.length;i++){
arr.push(mototext[i].name); arr.push(mototext[i].name);
} }
   //配列要素を,で連結して文字列を作成: //配列要素を,で連結して文字列を作成:
value=arr.join(); value=arr.join();
} }
//カテゴリー、チェックボックス、複数選択: //カテゴリー、チェックボックス、複数選択:
@@ -120,7 +120,7 @@ export class StringJoinAction implements IAction{
for(let i=0;i<mototext.length;i++){ for(let i=0;i<mototext.length;i++){
arr.push(mototext[i]); arr.push(mototext[i]);
} }
   //配列要素を,で連結して文字列を作成: //配列要素を,で連結して文字列を作成:
value=arr.join(); value=arr.join();
} }
//詳細画面プロセス実行後のステータス: //詳細画面プロセス実行後のステータス:

View File

@@ -66,6 +66,7 @@ export class FullWidthAction implements IAction{
result:true result:true
} }
return result; return result;
//例外処理 //例外処理
}catch(error){ }catch(error){
event.error=error; event.error=error;
@@ -74,26 +75,19 @@ export class FullWidthAction implements IAction{
return result; return result;
} }
} }
//全て全角の文字列の場合はtrue、そうでない場合はfalse // 全て全角の文字列の場合はtrue、そうでない場合はfalse
containsFullWidthChars(text: string): boolean { containsFullWidthChars(text: string): boolean {
//半角英数字カナを除外
// 半角英数字カナ記号を除外
const checkRegex="^[^\x01-\x7E\uFF61-\uFF9F]+$"; const checkRegex="^[^\x01-\x7E\uFF61-\uFF9F]+$";
//正規表現オブジェクト生成 //正規表現オブジェクト生成
const fullWidthRegex = new RegExp(checkRegex); const fullWidthRegex = new RegExp(checkRegex);
//正規表現チェック //正規表現チェック
return fullWidthRegex.test(text); return fullWidthRegex.test(text);
//全角を表すUnicodeの全角正規表現(参照先URL)
// \u3000-\u303F句読点・記号
// \u3040-\u309Fすべてのひらがな
// \u30A0-\u30FF:すべてのカタカナ
// \u4E00-\u9FAF:すべての漢字
// \uFF00-\uFFEF:全角英数字と半角カタカナ
// \u3400-\u4DBF:CJK統合漢字拡張
//const fullWidthRegex = /[/^[\u3000-\u303F\u3040-\u309F\u30A0-\u30FF\uFF00-\uFFEF\u4E00-\u9FAF\u3400-\u4DBF]+$/g;
} }
//戻り値を持たないためvoid型 //戻り値を持たないためvoid型
register(): void { register(): void {
actionAddins[this.name]=this; actionAddins[this.name]=this;

View File

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

View File

@@ -1,11 +1,11 @@
import { actionAddins } from "."; import { actionAddins } from ".";
import { IAction,IActionResult, IActionNode, IActionProperty, IField, IContext} from "../types/ActionTypes"; import { IAction,IActionResult, IActionNode, IActionProperty, IField, IContext, IVarName} from "../types/ActionTypes";
/** /**
* アクションの属性定義 * アクションの属性定義
*/ */
interface IGetValueProps{ interface IGetValueProps{
field:IField;//チェックするフィールドの対象 field:IField;//チェックするフィールドの対象
verName:string; verName:IVarName;
} }
/** /**
* 正規表現チェックアクション * 正規表現チェックアクション
@@ -19,7 +19,7 @@ export class GetValueAciton implements IAction{
this.actionProps=[]; this.actionProps=[];
this.props={ this.props={
field:{code:''}, field:{code:''},
verName:'' verName:{name:''}
} }
//アクションを登録する //アクションを登録する
this.register(); this.register();
@@ -46,7 +46,9 @@ export class GetValueAciton implements IAction{
//条件式の計算結果を取得 //条件式の計算結果を取得
const record = event.record; const record = event.record;
const value = record[this.props.field.code].value; const value = record[this.props.field.code].value;
context.variables[this.props.verName] = value; if(this.props.verName && this.props.verName.name!==''){
context.variables[this.props.verName.name] = value;
}
result = { result = {
canNext:true, canNext:true,
result:true result:true

View File

@@ -92,6 +92,11 @@ export interface IField{
required?:boolean; required?:boolean;
options?:string; options?:string;
} }
//変数のインターフェース
export interface IVarName{
name:string;
fields?:IVarName[];
}
/** /**
* アクションのプロパティ定義に基づいたクラス * アクションのプロパティ定義に基づいたクラス

View File

@@ -13,7 +13,9 @@ import '../actions/datetime-getter';
import '../actions/insert-value'; import '../actions/insert-value';
import '../actions/value-getter'; import '../actions/value-getter';
import '../actions/string-join'; import '../actions/string-join';
import '../actions/validation fullwidth'; import '../actions/validation-fullwidth';
import '../actions/validation-halfwidth';
import { ActionFlow,IActionFlow, IActionResult,IContext } from "./ActionTypes"; import { ActionFlow,IActionFlow, IActionResult,IContext } from "./ActionTypes";
export class ActionProcess{ export class ActionProcess{