From 5a5cd386350de96c9a306b1673048fb15ee311c3 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Tue, 18 Aug 2026 14:46:15 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20gitignore=20xls2ui=20CRUD=20=E4=BA=A7?= =?UTF-8?q?=E7=89=A9(llm/pipeline=5Fsteps/pipeline=5Fversions/pipelines)?= =?UTF-8?q?=20+=20build/egg-info=EF=BC=8C=E5=81=9C=E6=AD=A2=E8=B7=9F?= =?UTF-8?q?=E8=B8=AA=E6=9E=84=E5=BB=BA=E4=BA=A7=E7=89=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 11 + wwwroot/llm/add_llm.dspy | 51 ---- wwwroot/llm/delete_llm.dspy | 47 ---- wwwroot/llm/get_llm.dspy | 162 ------------ wwwroot/llm/index.ui | 207 --------------- wwwroot/llm/update_llm.dspy | 70 ----- .../pipeline_steps/add_pipeline_steps.dspy | 37 --- .../pipeline_steps/delete_pipeline_steps.dspy | 33 --- .../pipeline_steps/get_pipeline_steps.dspy | 14 - wwwroot/pipeline_steps/get_pipelines.dspy | 13 - wwwroot/pipeline_steps/get_step_types.dspy | 18 -- wwwroot/pipeline_steps/index.ui | 241 ----------------- .../pipeline_steps/update_pipeline_steps.dspy | 36 --- .../add_pipeline_versions.dspy | 37 --- .../delete_pipeline_versions.dspy | 33 --- .../get_pipeline_versions.dspy | 113 -------- wwwroot/pipeline_versions/index.ui | 210 --------------- .../update_pipeline_versions.dspy | 36 --- wwwroot/pipelines/add_pipelines.dspy | 54 ---- wwwroot/pipelines/delete_pipelines.dspy | 47 ---- wwwroot/pipelines/get_pipelines.dspy | 165 ------------ wwwroot/pipelines/index.ui | 244 ------------------ wwwroot/pipelines/update_pipelines.dspy | 73 ------ 23 files changed, 11 insertions(+), 1941 deletions(-) delete mode 100644 wwwroot/llm/add_llm.dspy delete mode 100644 wwwroot/llm/delete_llm.dspy delete mode 100644 wwwroot/llm/get_llm.dspy delete mode 100644 wwwroot/llm/index.ui delete mode 100644 wwwroot/llm/update_llm.dspy delete mode 100644 wwwroot/pipeline_steps/add_pipeline_steps.dspy delete mode 100644 wwwroot/pipeline_steps/delete_pipeline_steps.dspy delete mode 100644 wwwroot/pipeline_steps/get_pipeline_steps.dspy delete mode 100644 wwwroot/pipeline_steps/get_pipelines.dspy delete mode 100644 wwwroot/pipeline_steps/get_step_types.dspy delete mode 100644 wwwroot/pipeline_steps/index.ui delete mode 100644 wwwroot/pipeline_steps/update_pipeline_steps.dspy delete mode 100644 wwwroot/pipeline_versions/add_pipeline_versions.dspy delete mode 100644 wwwroot/pipeline_versions/delete_pipeline_versions.dspy delete mode 100644 wwwroot/pipeline_versions/get_pipeline_versions.dspy delete mode 100644 wwwroot/pipeline_versions/index.ui delete mode 100644 wwwroot/pipeline_versions/update_pipeline_versions.dspy delete mode 100644 wwwroot/pipelines/add_pipelines.dspy delete mode 100644 wwwroot/pipelines/delete_pipelines.dspy delete mode 100644 wwwroot/pipelines/get_pipelines.dspy delete mode 100644 wwwroot/pipelines/index.ui delete mode 100644 wwwroot/pipelines/update_pipelines.dspy diff --git a/.gitignore b/.gitignore index 3bbe7b6..c99e572 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,14 @@ __pycache__/ *.pyc *.pyo + +# pip / setuptools build artifacts +build/ +dist/ +*.egg-info/ + +# xls2ui 生成的 CRUD(build.sh 第 7 步从 json/*.json 重新生成,构建产物,不入库) +wwwroot/llm/ +wwwroot/pipeline_steps/ +wwwroot/pipeline_versions/ +wwwroot/pipelines/ diff --git a/wwwroot/llm/add_llm.dspy b/wwwroot/llm/add_llm.dspy deleted file mode 100644 index 7f1f689..0000000 --- a/wwwroot/llm/add_llm.dspy +++ /dev/null @@ -1,51 +0,0 @@ - -ns = params_kw.copy() -for k,v in ns.items(): - if v == 'NaN' or v == 'null': - ns[k] = None -id = params_kw.id -if not id or len(id) > 32: - id = uuid() -ns['id'] = id - - - -userorgid = await get_userorgid() -if not userorgid: - return { - "widgettype":"Error", - "options":{ - "title":"Authorization Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"Please login" - } - } -ns['org_id'] = userorgid - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.C('llm', ns.copy()) - return { - "widgettype":"Message", - "options":{ - "cwidth":16, - "cheight":9, - "title":"Add Success", - "timeout":3, - "message":"ok" - } - } - -return { - "widgettype":"Error", - "options":{ - "title":"Add Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/llm/delete_llm.dspy b/wwwroot/llm/delete_llm.dspy deleted file mode 100644 index 53760d5..0000000 --- a/wwwroot/llm/delete_llm.dspy +++ /dev/null @@ -1,47 +0,0 @@ - -ns = { - 'id':params_kw['id'], -} - - -userorgid = await get_userorgid() -if not userorgid: - return { - "widgettype":"Error", - "options":{ - "title":"Authorization Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"Please login" - } - } -ns['org_id'] = userorgid - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.D('llm', ns) - debug('delete success'); - return { - "widgettype":"Message", - "options":{ - "title":"Delete Success", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"ok" - } - } - -debug('Delete failed'); -return { - "widgettype":"Error", - "options":{ - "title":"Delete Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/llm/get_llm.dspy b/wwwroot/llm/get_llm.dspy deleted file mode 100644 index 325430a..0000000 --- a/wwwroot/llm/get_llm.dspy +++ /dev/null @@ -1,162 +0,0 @@ - -ns = params_kw.copy() - - -userorgid = await get_userorgid() -if not userorgid: - return { - "widgettype":"Error", - "options":{ - "title":"Authorization Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"Please login" - } - } -ns['org_id'] = userorgid -ns['userorgid'] = userorgid - -debug(f'get_llm.dspy:{ns=}') -if not ns.get('page'): - ns['page'] = 1 -if not ns.get('sort'): - - - ns['sort'] = 'created_at' - - - -sql = '''select * from llm where 1=1 [[filterstr]]''' - -filterjson = params_kw.get('data_filter') -if filterjson and isinstance(filterjson, str): - try: - filterjson = json.loads(filterjson) - except (json.JSONDecodeError, TypeError): - filterjson = None -fields_str=r'''[ - { - "name": "id", - "title": "主键", - "type": "str", - "length": 32, - "nullable": "no" - }, - { - "name": "name", - "title": "模型名称", - "type": "str", - "length": 100, - "nullable": "no" - }, - { - "name": "provider", - "title": "供应商", - "type": "str", - "length": 50, - "nullable": "no" - }, - { - "name": "model_id", - "title": "模型标识", - "type": "str", - "length": 100 - }, - { - "name": "api_base", - "title": "API地址", - "type": "str", - "length": 500 - }, - { - "name": "api_key", - "title": "API密钥", - "type": "str", - "length": 500 - }, - { - "name": "max_tokens", - "title": "最大Token", - "type": "int", - "default": "8192" - }, - { - "name": "status", - "title": "状态", - "type": "str", - "length": 20, - "default": "active" - }, - { - "name": "capabilities", - "title": "能力分类", - "type": "str", - "length": 20, - "default": "text" - }, - { - "name": "org_id", - "title": "所属机构ID", - "type": "str", - "length": 32, - "default": "0" - }, - { - "name": "description", - "title": "描述", - "type": "text" - }, - { - "name": "created_at", - "title": "创建时间", - "type": "timestamp" - }, - { - "name": "updated_at", - "title": "更新时间", - "type": "timestamp" - } -]''' -ori_fields = json.loads(fields_str) -if not filterjson: - fields = [ f['name'] for f in ori_fields ] - filterjson = default_filterjson(fields, ns) - -# 确保 logined 过滤条件始终生效 -if filterjson: - if not isinstance(filterjson, dict) or 'AND' not in filterjson: - filterjson = {'AND': [filterjson] if filterjson else []} - - filterjson['AND'].append({'field': 'org_id', 'op': '=', 'var': '__logined_orgid__'}) - ns['__logined_orgid__'] = userorgid - - - -filterdic = ns.copy() -filterdic['filterstr'] = '' -filterdic['userorgid'] = '${userorgid}$' -filterdic['userid'] = '${userid}$' -if filterjson: - dbf = DBFilter(filterjson) - conds = dbf.gen(ns) - if conds: - ns.update(dbf.consts) - conds = f' and {conds}' - filterdic['filterstr'] = conds -ac = ArgsConvert('[[', ']]') -vars = ac.findAllVariables(sql) -NameSpace = {v:'${' + v + '}$' for v in vars if v != 'filterstr' } -filterdic.update(NameSpace) -sql = ac.convert(sql, filterdic) - -debug(f'{sql=}') -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.sqlPaging(sql, ns) - return r -return { - "total":0, - "rows":[] -} \ No newline at end of file diff --git a/wwwroot/llm/index.ui b/wwwroot/llm/index.ui deleted file mode 100644 index 4aecf39..0000000 --- a/wwwroot/llm/index.ui +++ /dev/null @@ -1,207 +0,0 @@ - -{ - "widgettype":"VBox", - "options":{"cheight":40,"width":"100%"}, - "subwidgets":[{ - "id":"llm_tbl", - "widgettype":"Tabular", - "options":{ - "width":"100%", - "height":"100%", - - - "title":"大语言模型表", - - - - - "css":"card", - - - "editable":{ - - "new_data_url":"{{entire_url('add_llm.dspy')}}", - - - "delete_data_url":"{{entire_url('delete_llm.dspy')}}", - - - "update_data_url":"{{entire_url('update_llm.dspy')}}" - - }, - - - "data_url":"{{entire_url('./get_llm.dspy')}}", - - "data_method":"GET", - "data_params":{{json.dumps(params_kw, indent=4, ensure_ascii=False)}}, - "row_options":{ - - - - "browserfields": { - "exclouded": [ - "id", - "api_key" - ], - "cwidth": {} -}, - - - "editexclouded":[ - "id", - "created_at", - "updated_at" -], - - "fields":[ - { - "name": "id", - "title": "主键", - "type": "str", - "length": 32, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "主键" - }, - { - "name": "name", - "title": "模型名称", - "type": "str", - "length": 100, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "模型名称" - }, - { - "name": "provider", - "title": "供应商", - "type": "str", - "length": 50, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "供应商" - }, - { - "name": "model_id", - "title": "模型标识", - "type": "str", - "length": 100, - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "模型标识" - }, - { - "name": "api_base", - "title": "API地址", - "type": "str", - "length": 500, - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "API地址" - }, - { - "name": "api_key", - "title": "API密钥", - "type": "str", - "length": 500, - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "API密钥" - }, - { - "name": "max_tokens", - "title": "最大Token", - "type": "int", - "default": "8192", - "length": 0, - "uitype": "int", - "datatype": "int", - "label": "最大Token" - }, - { - "name": "status", - "title": "状态", - "type": "str", - "length": 20, - "default": "active", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "状态" - }, - { - "name": "capabilities", - "title": "能力分类", - "type": "str", - "length": 20, - "default": "text", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "能力分类" - }, - { - "name": "org_id", - "title": "所属机构ID", - "type": "str", - "length": 32, - "default": "0", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "所属机构ID" - }, - { - "name": "description", - "title": "描述", - "type": "text", - "length": 0, - "uitype": "text", - "datatype": "text", - "label": "描述" - }, - { - "name": "created_at", - "title": "创建时间", - "type": "timestamp", - "length": 0, - "uitype": "str", - "datatype": "timestamp", - "label": "创建时间" - }, - { - "name": "updated_at", - "title": "更新时间", - "type": "timestamp", - "length": 0, - "uitype": "str", - "datatype": "timestamp", - "label": "更新时间" - } -] - }, - - - - - - - - "page_rows":160, - "cache_limit":5 - } - - ,"binds":[] - -}] -} \ No newline at end of file diff --git a/wwwroot/llm/update_llm.dspy b/wwwroot/llm/update_llm.dspy deleted file mode 100644 index b54b0a5..0000000 --- a/wwwroot/llm/update_llm.dspy +++ /dev/null @@ -1,70 +0,0 @@ - -ns = params_kw.copy() -for k,v in ns.items(): - if v == 'NaN' or v == 'null': - ns[k] = None - - -userorgid = await get_userorgid() -if not userorgid: - return { - "widgettype":"Error", - "options":{ - "title":"Authorization Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"Please login" - } - } -ns['org_id'] = userorgid - - - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - - ns1 = { - - "org_id": userorgid, - - - "id": params_kw.id - } - recs = await sor.R('llm', ns1) - if len(recs) < 1: - return { - "widgettype":"Error", - "options":{ - "title":"Update Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"Record no exist or with wrong ownership" - } - } - - r = await sor.U('llm', ns) - debug('update success'); - return { - "widgettype":"Message", - "options":{ - "title":"Update Success", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"ok" - } - } - -return { - "widgettype":"Error", - "options":{ - "title":"Update Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/pipeline_steps/add_pipeline_steps.dspy b/wwwroot/pipeline_steps/add_pipeline_steps.dspy deleted file mode 100644 index 098b2fc..0000000 --- a/wwwroot/pipeline_steps/add_pipeline_steps.dspy +++ /dev/null @@ -1,37 +0,0 @@ - -ns = params_kw.copy() -for k,v in ns.items(): - if v == 'NaN' or v == 'null': - ns[k] = None -id = params_kw.id -if not id or len(id) > 32: - id = uuid() -ns['id'] = id - - - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.C('pipeline_steps', ns.copy()) - return { - "widgettype":"Message", - "options":{ - "cwidth":16, - "cheight":9, - "title":"Add Success", - "timeout":3, - "message":"ok" - } - } - -return { - "widgettype":"Error", - "options":{ - "title":"Add Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/pipeline_steps/delete_pipeline_steps.dspy b/wwwroot/pipeline_steps/delete_pipeline_steps.dspy deleted file mode 100644 index d659f20..0000000 --- a/wwwroot/pipeline_steps/delete_pipeline_steps.dspy +++ /dev/null @@ -1,33 +0,0 @@ - -ns = { - 'id':params_kw['id'], -} - - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.D('pipeline_steps', ns) - debug('delete success'); - return { - "widgettype":"Message", - "options":{ - "title":"Delete Success", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"ok" - } - } - -debug('Delete failed'); -return { - "widgettype":"Error", - "options":{ - "title":"Delete Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/pipeline_steps/get_pipeline_steps.dspy b/wwwroot/pipeline_steps/get_pipeline_steps.dspy deleted file mode 100644 index 5a6875b..0000000 --- a/wwwroot/pipeline_steps/get_pipeline_steps.dspy +++ /dev/null @@ -1,14 +0,0 @@ - -from sqlor.dbpools import DBPools - -async def main(): - pipeline_id = params_kw.pipeline_id or params_kw.id - dbname = get_module_dbname('pipeline_core') - async with DBPools().sqlorContext(dbname) as sor: - if pipeline_id: - recs = await sor.R('pipeline_steps', {'pipeline_id': pipeline_id}) - else: - recs = await sor.R('pipeline_steps', {}) - # Sort by step_order - recs = sorted(recs, key=lambda r: r.step_order if hasattr(r,'step_order') else 0) - return recs diff --git a/wwwroot/pipeline_steps/get_pipelines.dspy b/wwwroot/pipeline_steps/get_pipelines.dspy deleted file mode 100644 index 2034836..0000000 --- a/wwwroot/pipeline_steps/get_pipelines.dspy +++ /dev/null @@ -1,13 +0,0 @@ - -from sqlor.dbpools import DBPools - -async def main(): - dbname = get_module_dbname('pipeline_core') - async with DBPools().sqlorContext(dbname) as sor: - recs = await sor.R('pipelines', {'status': 'published'}) - if not recs: - recs = await sor.R('pipelines', {}) - result = [] - for r in recs: - result.append({'id': r.id, 'name': r.name, 'text': r.name, 'value': r.id}) - return result diff --git a/wwwroot/pipeline_steps/get_step_types.dspy b/wwwroot/pipeline_steps/get_step_types.dspy deleted file mode 100644 index 85881c1..0000000 --- a/wwwroot/pipeline_steps/get_step_types.dspy +++ /dev/null @@ -1,18 +0,0 @@ - -from sqlor.dbpools import DBPools - -async def main(): - dbname = get_module_dbname('pipeline_core') - async with DBPools().sqlorContext(dbname) as sor: - recs = await sor.R('pipeline_step_types', {}) - result = [] - for r in recs: - result.append({ - 'step_type': r.step_type, - 'display_name': r.display_name, - 'text': f"{r.display_name} ({r.step_type})", - 'value': r.step_type, - 'category': r.category, - 'is_interactive': r.is_interactive - }) - return result diff --git a/wwwroot/pipeline_steps/index.ui b/wwwroot/pipeline_steps/index.ui deleted file mode 100644 index f0e6f1f..0000000 --- a/wwwroot/pipeline_steps/index.ui +++ /dev/null @@ -1,241 +0,0 @@ - -{ - "widgettype":"VBox", - "options":{"cheight":40,"width":"100%"}, - "subwidgets":[{ - "id":"pipeline_steps_tbl", - "widgettype":"Tabular", - "options":{ - "width":"100%", - "height":"100%", - - - "title":"产线步骤表", - - - - - "toolbar":{ - "tools": [ - { - "selected_row": true, - "name": "pipelines", - "icon": "{{entire_url('/imgs/pipelines.svg')}}", - "label": "所属产线" - } - ] -}, - - "css":"card", - - - "editable":{ - - "new_data_url":"{{entire_url('add_pipeline_steps.dspy')}}", - - - "delete_data_url":"{{entire_url('delete_pipeline_steps.dspy')}}", - - - "update_data_url":"{{entire_url('update_pipeline_steps.dspy')}}" - - }, - - - "data_url":"{{entire_url('./get_pipeline_steps.dspy')}}", - - "data_method":"GET", - "data_params":{{json.dumps(params_kw, indent=4, ensure_ascii=False)}}, - "row_options":{ - - - - "browserfields": { - "exclouded": [ - "id", - "step_config", - "input_schema", - "output_schema" - ], - "cwidth": {} -}, - - - "editexclouded":[ - "id", - "created_at" -], - - "fields":[ - { - "name": "id", - "title": "id", - "type": "str", - "length": 32, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "id" - }, - { - "name": "pipeline_id", - "title": "所属产线", - "type": "str", - "length": 32, - "nullable": "no", - "label": "所属产线", - "uitype": "code", - "valueField": "pipeline_id", - "textField": "pipeline_id_text", - "params": { - "dbname": "{{'sage'}}", - "table": "pipelines", - "tblvalue": "id", - "tbltext": "name", - "valueField": "pipeline_id", - "textField": "pipeline_id_text" - }, - "dataurl": "{{entire_url('/appbase/get_code.dspy')}}" - }, - { - "name": "step_order", - "title": "步骤序号", - "type": "int", - "nullable": "no", - "length": 0, - "uitype": "int", - "datatype": "int", - "label": "步骤序号" - }, - { - "name": "step_name", - "title": "步骤名称", - "type": "str", - "length": 100, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "步骤名称" - }, - { - "name": "step_type", - "title": "步骤类型", - "type": "str", - "length": 50, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "步骤类型" - }, - { - "name": "model_name", - "title": "调用模型名称", - "type": "str", - "length": 100, - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "调用模型名称" - }, - { - "name": "step_config", - "title": "步骤配置JSON", - "type": "text", - "length": 0, - "uitype": "text", - "datatype": "text", - "label": "步骤配置JSON" - }, - { - "name": "input_schema", - "title": "输入定义JSON", - "type": "text", - "length": 0, - "uitype": "text", - "datatype": "text", - "label": "输入定义JSON" - }, - { - "name": "output_schema", - "title": "输出定义JSON", - "type": "text", - "length": 0, - "uitype": "text", - "datatype": "text", - "label": "输出定义JSON" - }, - { - "name": "timeout_seconds", - "title": "超时秒数", - "type": "int", - "default": "300", - "length": 0, - "uitype": "int", - "datatype": "int", - "label": "超时秒数" - }, - { - "name": "retry_count", - "title": "重试次数", - "type": "int", - "default": "0", - "length": 0, - "uitype": "int", - "datatype": "int", - "label": "重试次数" - }, - { - "name": "created_at", - "title": "创建时间", - "type": "timestamp", - "length": 0, - "uitype": "str", - "datatype": "timestamp", - "label": "创建时间" - } -] - }, - - - - - - - - "page_rows":160, - "cache_limit":5 - } - - ,"binds":[ - { - "wid": "self", - "event": "pipelines", - "actiontype": "urlwidget", - "target": "PopupWindow", - "popup_options": { - "title": "所属产线", - "icon": "{{entire_url('/appbase/get_icon.dspy')}}?id=pipelines", - "resizable": true, - "height": "70%", - "width": "70%" - }, - "params_mapping": { - "mapping": { - "id": "pipeline_id", - "referer_widget": "referer_widget" - }, - "need_other": false - }, - "options": { - "method": "POST", - "params": {}, - "url": "{{entire_url('../pipelines')}}" - } - } -] - -}] -} \ No newline at end of file diff --git a/wwwroot/pipeline_steps/update_pipeline_steps.dspy b/wwwroot/pipeline_steps/update_pipeline_steps.dspy deleted file mode 100644 index 9c095da..0000000 --- a/wwwroot/pipeline_steps/update_pipeline_steps.dspy +++ /dev/null @@ -1,36 +0,0 @@ - -ns = params_kw.copy() -for k,v in ns.items(): - if v == 'NaN' or v == 'null': - ns[k] = None - - - - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - - r = await sor.U('pipeline_steps', ns) - debug('update success'); - return { - "widgettype":"Message", - "options":{ - "title":"Update Success", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"ok" - } - } - -return { - "widgettype":"Error", - "options":{ - "title":"Update Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/pipeline_versions/add_pipeline_versions.dspy b/wwwroot/pipeline_versions/add_pipeline_versions.dspy deleted file mode 100644 index 15c2ddb..0000000 --- a/wwwroot/pipeline_versions/add_pipeline_versions.dspy +++ /dev/null @@ -1,37 +0,0 @@ - -ns = params_kw.copy() -for k,v in ns.items(): - if v == 'NaN' or v == 'null': - ns[k] = None -id = params_kw.id -if not id or len(id) > 32: - id = uuid() -ns['id'] = id - - - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.C('pipeline_versions', ns.copy()) - return { - "widgettype":"Message", - "options":{ - "cwidth":16, - "cheight":9, - "title":"Add Success", - "timeout":3, - "message":"ok" - } - } - -return { - "widgettype":"Error", - "options":{ - "title":"Add Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/pipeline_versions/delete_pipeline_versions.dspy b/wwwroot/pipeline_versions/delete_pipeline_versions.dspy deleted file mode 100644 index 42a6efb..0000000 --- a/wwwroot/pipeline_versions/delete_pipeline_versions.dspy +++ /dev/null @@ -1,33 +0,0 @@ - -ns = { - 'id':params_kw['id'], -} - - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.D('pipeline_versions', ns) - debug('delete success'); - return { - "widgettype":"Message", - "options":{ - "title":"Delete Success", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"ok" - } - } - -debug('Delete failed'); -return { - "widgettype":"Error", - "options":{ - "title":"Delete Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/pipeline_versions/get_pipeline_versions.dspy b/wwwroot/pipeline_versions/get_pipeline_versions.dspy deleted file mode 100644 index b039ebd..0000000 --- a/wwwroot/pipeline_versions/get_pipeline_versions.dspy +++ /dev/null @@ -1,113 +0,0 @@ - -ns = params_kw.copy() - - -debug(f'get_pipeline_versions.dspy:{ns=}') -if not ns.get('page'): - ns['page'] = 1 -if not ns.get('sort'): - - - ns['sort'] = 'created_at' - - - -sql = '''select a.*, b.pipeline_id_text -from (select * from pipeline_versions where 1=1 [[filterstr]]) a left join (select id as pipeline_id, - name as pipeline_id_text from pipelines where 1 = 1) b on a.pipeline_id = b.pipeline_id''' - -filterjson = params_kw.get('data_filter') -if filterjson and isinstance(filterjson, str): - try: - filterjson = json.loads(filterjson) - except (json.JSONDecodeError, TypeError): - filterjson = None -fields_str=r'''[ - { - "name": "id", - "title": "id", - "type": "str", - "length": 32, - "nullable": "no" - }, - { - "name": "pipeline_id", - "title": "产线ID", - "type": "str", - "length": 32, - "nullable": "no" - }, - { - "name": "version", - "title": "版本号", - "type": "str", - "length": 20, - "nullable": "no" - }, - { - "name": "publish_status", - "title": "发布状态", - "type": "str", - "length": 20, - "nullable": "no", - "default": "pending" - }, - { - "name": "published_by", - "title": "发布人", - "type": "str", - "length": 32 - }, - { - "name": "published_at", - "title": "发布时间", - "type": "timestamp" - }, - { - "name": "changelog", - "title": "变更说明", - "type": "text" - }, - { - "name": "config_snapshot", - "title": "配置快照JSON", - "type": "text" - }, - { - "name": "created_at", - "title": "创建时间", - "type": "timestamp" - } -]''' -ori_fields = json.loads(fields_str) -if not filterjson: - fields = [ f['name'] for f in ori_fields ] - filterjson = default_filterjson(fields, ns) - -filterdic = ns.copy() -filterdic['filterstr'] = '' -filterdic['userorgid'] = '${userorgid}$' -filterdic['userid'] = '${userid}$' -if filterjson: - dbf = DBFilter(filterjson) - conds = dbf.gen(ns) - if conds: - ns.update(dbf.consts) - conds = f' and {conds}' - filterdic['filterstr'] = conds -ac = ArgsConvert('[[', ']]') -vars = ac.findAllVariables(sql) -NameSpace = {v:'${' + v + '}$' for v in vars if v != 'filterstr' } -filterdic.update(NameSpace) -sql = ac.convert(sql, filterdic) - -debug(f'{sql=}') -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.sqlPaging(sql, ns) - return r -return { - "total":0, - "rows":[] -} \ No newline at end of file diff --git a/wwwroot/pipeline_versions/index.ui b/wwwroot/pipeline_versions/index.ui deleted file mode 100644 index 79265b7..0000000 --- a/wwwroot/pipeline_versions/index.ui +++ /dev/null @@ -1,210 +0,0 @@ - -{ - "widgettype":"VBox", - "options":{"cheight":40,"width":"100%"}, - "subwidgets":[{ - "id":"pipeline_versions_tbl", - "widgettype":"Tabular", - "options":{ - "width":"100%", - "height":"100%", - - - "title":"产线发布记录表", - - - - - "toolbar":{ - "tools": [ - { - "selected_row": true, - "name": "pipelines", - "icon": "{{entire_url('/imgs/pipelines.svg')}}", - "label": "所属产线" - } - ] -}, - - "css":"card", - - - "editable":{ - - "new_data_url":"{{entire_url('add_pipeline_versions.dspy')}}", - - - "delete_data_url":"{{entire_url('delete_pipeline_versions.dspy')}}", - - - "update_data_url":"{{entire_url('update_pipeline_versions.dspy')}}" - - }, - - - "data_url":"{{entire_url('./get_pipeline_versions.dspy')}}", - - "data_method":"GET", - "data_params":{{json.dumps(params_kw, indent=4, ensure_ascii=False)}}, - "row_options":{ - - - - "browserfields": { - "exclouded": [ - "id", - "config_snapshot" - ], - "cwidth": {} -}, - - - "editexclouded":[ - "id", - "created_at" -], - - "fields":[ - { - "name": "id", - "title": "id", - "type": "str", - "length": 32, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "id" - }, - { - "name": "pipeline_id", - "title": "产线ID", - "type": "str", - "length": 32, - "nullable": "no", - "label": "产线ID", - "uitype": "code", - "valueField": "pipeline_id", - "textField": "pipeline_id_text", - "params": { - "dbname": "{{'sage'}}", - "table": "pipelines", - "tblvalue": "id", - "tbltext": "name", - "valueField": "pipeline_id", - "textField": "pipeline_id_text" - }, - "dataurl": "{{entire_url('/appbase/get_code.dspy')}}" - }, - { - "name": "version", - "title": "版本号", - "type": "str", - "length": 20, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "版本号" - }, - { - "name": "publish_status", - "title": "发布状态", - "type": "str", - "length": 20, - "nullable": "no", - "default": "pending", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "发布状态" - }, - { - "name": "published_by", - "title": "发布人", - "type": "str", - "length": 32, - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "发布人" - }, - { - "name": "published_at", - "title": "发布时间", - "type": "timestamp", - "length": 0, - "uitype": "str", - "datatype": "timestamp", - "label": "发布时间" - }, - { - "name": "changelog", - "title": "变更说明", - "type": "text", - "length": 0, - "uitype": "text", - "datatype": "text", - "label": "变更说明" - }, - { - "name": "config_snapshot", - "title": "配置快照JSON", - "type": "text", - "length": 0, - "uitype": "text", - "datatype": "text", - "label": "配置快照JSON" - }, - { - "name": "created_at", - "title": "创建时间", - "type": "timestamp", - "length": 0, - "uitype": "str", - "datatype": "timestamp", - "label": "创建时间" - } -] - }, - - - - - - - - "page_rows":160, - "cache_limit":5 - } - - ,"binds":[ - { - "wid": "self", - "event": "pipelines", - "actiontype": "urlwidget", - "target": "PopupWindow", - "popup_options": { - "title": "所属产线", - "icon": "{{entire_url('/appbase/get_icon.dspy')}}?id=pipelines", - "resizable": true, - "height": "70%", - "width": "70%" - }, - "params_mapping": { - "mapping": { - "id": "pipeline_id", - "referer_widget": "referer_widget" - }, - "need_other": false - }, - "options": { - "method": "POST", - "params": {}, - "url": "{{entire_url('../pipelines')}}" - } - } -] - -}] -} \ No newline at end of file diff --git a/wwwroot/pipeline_versions/update_pipeline_versions.dspy b/wwwroot/pipeline_versions/update_pipeline_versions.dspy deleted file mode 100644 index 74b8082..0000000 --- a/wwwroot/pipeline_versions/update_pipeline_versions.dspy +++ /dev/null @@ -1,36 +0,0 @@ - -ns = params_kw.copy() -for k,v in ns.items(): - if v == 'NaN' or v == 'null': - ns[k] = None - - - - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - - r = await sor.U('pipeline_versions', ns) - debug('update success'); - return { - "widgettype":"Message", - "options":{ - "title":"Update Success", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"ok" - } - } - -return { - "widgettype":"Error", - "options":{ - "title":"Update Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/pipelines/add_pipelines.dspy b/wwwroot/pipelines/add_pipelines.dspy deleted file mode 100644 index 9972d78..0000000 --- a/wwwroot/pipelines/add_pipelines.dspy +++ /dev/null @@ -1,54 +0,0 @@ - -ns = params_kw.copy() -for k,v in ns.items(): - if v == 'NaN' or v == 'null': - ns[k] = None -id = params_kw.id -if not id or len(id) > 32: - id = uuid() -ns['id'] = id - -if params_kw.get('model_api_key'): - ns['model_api_key'] = password_encode(params_kw.get('model_api_key')) - - - -userorgid = await get_userorgid() -if not userorgid: - return { - "widgettype":"Error", - "options":{ - "title":"Authorization Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"Please login" - } - } -ns['org_id'] = userorgid - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.C('pipelines', ns.copy()) - return { - "widgettype":"Message", - "options":{ - "cwidth":16, - "cheight":9, - "title":"Add Success", - "timeout":3, - "message":"ok" - } - } - -return { - "widgettype":"Error", - "options":{ - "title":"Add Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/pipelines/delete_pipelines.dspy b/wwwroot/pipelines/delete_pipelines.dspy deleted file mode 100644 index f2318f0..0000000 --- a/wwwroot/pipelines/delete_pipelines.dspy +++ /dev/null @@ -1,47 +0,0 @@ - -ns = { - 'id':params_kw['id'], -} - - -userorgid = await get_userorgid() -if not userorgid: - return { - "widgettype":"Error", - "options":{ - "title":"Authorization Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"Please login" - } - } -ns['org_id'] = userorgid - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.D('pipelines', ns) - debug('delete success'); - return { - "widgettype":"Message", - "options":{ - "title":"Delete Success", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"ok" - } - } - -debug('Delete failed'); -return { - "widgettype":"Error", - "options":{ - "title":"Delete Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"failed" - } -} \ No newline at end of file diff --git a/wwwroot/pipelines/get_pipelines.dspy b/wwwroot/pipelines/get_pipelines.dspy deleted file mode 100644 index 129b5d1..0000000 --- a/wwwroot/pipelines/get_pipelines.dspy +++ /dev/null @@ -1,165 +0,0 @@ - -ns = params_kw.copy() - - -userorgid = await get_userorgid() -if not userorgid: - return { - "widgettype":"Error", - "options":{ - "title":"Authorization Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"Please login" - } - } -ns['org_id'] = userorgid -ns['userorgid'] = userorgid - -debug(f'get_pipelines.dspy:{ns=}') -if not ns.get('page'): - ns['page'] = 1 -if not ns.get('sort'): - - - ns['sort'] = 'created_at' - - - -sql = '''select a.*, b.pipeline_type_text, c.status_text -from (select * from pipelines where 1=1 [[filterstr]]) a left join (select k as pipeline_type, - v as pipeline_type_text from appcodes_kv where parentid='pipeline_type') b on a.pipeline_type = b.pipeline_type left join (select k as status, - v as status_text from appcodes_kv where parentid='pipeline_status') c on a.status = c.status''' - -filterjson = params_kw.get('data_filter') -if filterjson and isinstance(filterjson, str): - try: - filterjson = json.loads(filterjson) - except (json.JSONDecodeError, TypeError): - filterjson = None -fields_str=r'''[ - { - "name": "id", - "title": "id", - "type": "str", - "length": 32, - "nullable": "no" - }, - { - "name": "name", - "title": "产线名称", - "type": "str", - "length": 200, - "nullable": "no" - }, - { - "name": "description", - "title": "产线描述", - "type": "text" - }, - { - "name": "pipeline_type", - "title": "产线类型", - "type": "str", - "length": 50, - "nullable": "no" - }, - { - "name": "version", - "title": "当前版本", - "type": "str", - "length": 20, - "default": "1.0.0" - }, - { - "name": "status", - "title": "状态", - "type": "str", - "length": 20, - "nullable": "no", - "default": "draft" - }, - { - "name": "pipeline_config", - "title": "产线配置JSON", - "type": "text" - }, - { - "name": "model_api_url", - "title": "模型API地址", - "type": "str", - "length": 500 - }, - { - "name": "model_api_key", - "title": "模型API密钥", - "type": "str", - "length": 500 - }, - { - "name": "org_id", - "title": "所属机构ID", - "type": "str", - "length": 32, - "default": "0" - }, - { - "name": "created_by", - "title": "创建人", - "type": "str", - "length": 32 - }, - { - "name": "created_at", - "title": "创建时间", - "type": "timestamp" - }, - { - "name": "updated_at", - "title": "更新时间", - "type": "timestamp" - } -]''' -ori_fields = json.loads(fields_str) -if not filterjson: - fields = [ f['name'] for f in ori_fields ] - filterjson = default_filterjson(fields, ns) - -# 确保 logined 过滤条件始终生效 -if filterjson: - if not isinstance(filterjson, dict) or 'AND' not in filterjson: - filterjson = {'AND': [filterjson] if filterjson else []} - - filterjson['AND'].append({'field': 'org_id', 'op': '=', 'var': '__logined_orgid__'}) - ns['__logined_orgid__'] = userorgid - - - -filterdic = ns.copy() -filterdic['filterstr'] = '' -filterdic['userorgid'] = '${userorgid}$' -filterdic['userid'] = '${userid}$' -if filterjson: - dbf = DBFilter(filterjson) - conds = dbf.gen(ns) - if conds: - ns.update(dbf.consts) - conds = f' and {conds}' - filterdic['filterstr'] = conds -ac = ArgsConvert('[[', ']]') -vars = ac.findAllVariables(sql) -NameSpace = {v:'${' + v + '}$' for v in vars if v != 'filterstr' } -filterdic.update(NameSpace) -sql = ac.convert(sql, filterdic) - -debug(f'{sql=}') -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - r = await sor.sqlPaging(sql, ns) - return r -return { - "total":0, - "rows":[] -} \ No newline at end of file diff --git a/wwwroot/pipelines/index.ui b/wwwroot/pipelines/index.ui deleted file mode 100644 index 1f7e465..0000000 --- a/wwwroot/pipelines/index.ui +++ /dev/null @@ -1,244 +0,0 @@ - -{ - "widgettype":"VBox", - "options":{"cheight":40,"width":"100%"}, - "subwidgets":[{ - "id":"pipelines_tbl", - "widgettype":"Tabular", - "options":{ - "width":"100%", - "height":"100%", - - - "title":"产线定义表", - - - - - "css":"card", - - - "toolbar":{ - "tools":[ - { - "name":"publish", - "label":"发布", - "selected_row":true - } - ] - }, - - "editable":{ - - "new_data_url":"{{entire_url('add_pipelines.dspy')}}", - - - "delete_data_url":"{{entire_url('delete_pipelines.dspy')}}", - - - "update_data_url":"{{entire_url('update_pipelines.dspy')}}" - - }, - - - "data_url":"{{entire_url('./get_pipelines.dspy')}}", - - "data_method":"GET", - "data_params":{{json.dumps(params_kw, indent=4, ensure_ascii=False)}}, - "row_options":{ - - - - "browserfields": { - "exclouded": [ - "id", - "model_api_key", - "pipeline_config" - ], - "cwidth": {} -}, - - - "editexclouded":[ - "id", - "created_at", - "updated_at" -], - - "fields":[ - { - "name": "id", - "title": "id", - "type": "str", - "length": 32, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "id" - }, - { - "name": "name", - "title": "产线名称", - "type": "str", - "length": 200, - "nullable": "no", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "产线名称" - }, - { - "name": "description", - "title": "产线描述", - "type": "text", - "length": 0, - "uitype": "text", - "datatype": "text", - "label": "产线描述" - }, - { - "name": "pipeline_type", - "title": "产线类型", - "type": "str", - "length": 50, - "nullable": "no", - "label": "产线类型", - "uitype": "code", - "valueField": "pipeline_type", - "textField": "pipeline_type_text", - "params": { - "dbname": "{{{{get_module_dbname('pipeline_core')}}}}", - "table": "appcodes_kv", - "tblvalue": "k", - "tbltext": "v", - "valueField": "pipeline_type", - "textField": "pipeline_type_text", - "cond": "parentid='pipeline_type'" - }, - "dataurl": "{{entire_url('/appbase/get_code.dspy')}}" - }, - { - "name": "version", - "title": "当前版本", - "type": "str", - "length": 20, - "default": "1.0.0", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "当前版本" - }, - { - "name": "status", - "title": "状态", - "type": "str", - "length": 20, - "nullable": "no", - "default": "draft", - "label": "状态", - "uitype": "code", - "valueField": "status", - "textField": "status_text", - "params": { - "dbname": "{{{{get_module_dbname('pipeline_core')}}}}", - "table": "appcodes_kv", - "tblvalue": "k", - "tbltext": "v", - "valueField": "status", - "textField": "status_text", - "cond": "parentid='pipeline_status'" - }, - "dataurl": "{{entire_url('/appbase/get_code.dspy')}}" - }, - { - "name": "pipeline_config", - "title": "产线配置JSON", - "type": "text", - "length": 0, - "uitype": "text", - "datatype": "text", - "label": "产线配置JSON" - }, - { - "name": "model_api_url", - "title": "模型API地址", - "type": "str", - "length": 500, - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "模型API地址" - }, - { - "name": "model_api_key", - "title": "模型API密钥", - "type": "str", - "length": 500, - "cwidth": 18, - "uitype": "password", - "datatype": "str", - "label": "模型API密钥" - }, - { - "name": "org_id", - "title": "所属机构ID", - "type": "str", - "length": 32, - "default": "0", - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "所属机构ID" - }, - { - "name": "created_by", - "title": "创建人", - "type": "str", - "length": 32, - "cwidth": 18, - "uitype": "str", - "datatype": "str", - "label": "创建人" - }, - { - "name": "created_at", - "title": "创建时间", - "type": "timestamp", - "length": 0, - "uitype": "str", - "datatype": "timestamp", - "label": "创建时间" - }, - { - "name": "updated_at", - "title": "更新时间", - "type": "timestamp", - "length": 0, - "uitype": "str", - "datatype": "timestamp", - "label": "更新时间" - } -] - }, - - - - - - - - "page_rows":160, - "cache_limit":5 - } - - ,"binds":[{ - "wid":"self", - "event":"publish", - "actiontype":"script", - "target":"self", - "script":"var d=this.select_row.user_data;fetch('{{entire_url('../api/pipeline_publish.dspy')}}',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'pipeline_id='+encodeURIComponent(d.id)}).then(function(r){return r.json()}).then(function(r){if(r.success){this.render({})}else{bricks.show_error({title:'发布失败',message:r.message||'未知错误'})}}.bind(this))" - }] - -}] -} \ No newline at end of file diff --git a/wwwroot/pipelines/update_pipelines.dspy b/wwwroot/pipelines/update_pipelines.dspy deleted file mode 100644 index b777b85..0000000 --- a/wwwroot/pipelines/update_pipelines.dspy +++ /dev/null @@ -1,73 +0,0 @@ - -ns = params_kw.copy() -for k,v in ns.items(): - if v == 'NaN' or v == 'null': - ns[k] = None - - -userorgid = await get_userorgid() -if not userorgid: - return { - "widgettype":"Error", - "options":{ - "title":"Authorization Error", - "timeout":3, - "cwidth":16, - "cheight":9, - "message":"Please login" - } - } -ns['org_id'] = userorgid - - -if params_kw.get('model_api_key'): - ns['model_api_key'] = password_encode(params_kw.get('model_api_key')) - - -db = DBPools() -dbname = get_module_dbname('pipeline_core') -async with db.sqlorContext(dbname) as sor: - - ns1 = { - - "org_id": userorgid, - - - "id": params_kw.id - } - recs = await sor.R('pipelines', ns1) - if len(recs) < 1: - return { - "widgettype":"Error", - "options":{ - "title":"Update Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"Record no exist or with wrong ownership" - } - } - - r = await sor.U('pipelines', ns) - debug('update success'); - return { - "widgettype":"Message", - "options":{ - "title":"Update Success", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"ok" - } - } - -return { - "widgettype":"Error", - "options":{ - "title":"Update Error", - "cwidth":16, - "cheight":9, - "timeout":3, - "message":"failed" - } -} \ No newline at end of file