From d95c0c5a47217e9f90880aef832d2214b056b1b2 Mon Sep 17 00:00:00 2001 From: Chunlin Zhang Date: 2019年1月18日 17:02:12 +0800 Subject: [PATCH 1/2] add apijson-table edit feature --- demo/apps/tables/settings.ini | 36 ++++ demo/apps/tables/templates/Tables/list.html | 5 +- demo/apps/tables/views.py | 16 +- uliweb_apijson/apijson/__init__.py | 17 ++ uliweb_apijson/apijson/settings.ini | 3 + .../templates/vue/inc_apijson_table.html | 154 ++++++++++++++---- uliweb_apijson/apijson/views.py | 6 +- 7 files changed, 194 insertions(+), 43 deletions(-) create mode 100644 demo/apps/tables/settings.ini diff --git a/demo/apps/tables/settings.ini b/demo/apps/tables/settings.ini new file mode 100644 index 0000000..9ef7bb7 --- /dev/null +++ b/demo/apps/tables/settings.ini @@ -0,0 +1,36 @@ +[APIJSON_TABLES] +moment = { + "editable" : "auto", + "table_fields" : [ + {"title":"#","key":"id","width":80}, + {"title":"User id","key":"user_id","width":100}, + {"title":"Date","key":"date","width":160}, + {"title":"Content","key":"content"}, + ], + "viewedit_fields" : [ + {"title":"#","key":"id","editable":False}, + {"title":"User id","key":"user_id"}, + {"title":"Date","key":"date","editable":False}, + {"title":"Content","key":"content","type":"textarea"}, + ], +} + +comment = { + "editable" : "auto", + "table_fields" : [ + {"title":"#","key":"id","width":80}, + {"title":"User id","key":"user_id","width":100}, + {"title":"To id","key":"to_id","width":100}, + {"title":"Moment id","key":"moment_id","width":100}, + {"title":"Date","key":"date","width":160}, + {"title":"Content","key":"content"}, + ], + "viewedit_fields" : [ + {"title":"#","key":"id","editable":False}, + {"title":"User id","key":"user_id"}, + {"title":"To id","key":"to_id","editable":False}, + {"title":"Moment id","key":"moment_id","editable":False}, + {"title":"Date","key":"date","editable":False}, + {"title":"Content","key":"content","type":"textarea"}, + ], +} diff --git a/demo/apps/tables/templates/Tables/list.html b/demo/apps/tables/templates/Tables/list.html index 510663a..3b30919 100644 --- a/demo/apps/tables/templates/Tables/list.html +++ b/demo/apps/tables/templates/Tables/list.html @@ -10,7 +10,7 @@
- +
@@ -21,7 +21,8 @@ delimiters: ['{', '}'], data:{ tab_current: null, - tabs: {{=table_keys_json}} + tabs: {{=table_keys_json}}, + apijson_tables: {{=apijson_tables_json}} } }) diff --git a/demo/apps/tables/views.py b/demo/apps/tables/views.py index 1aa5f8d..095b181 100644 --- a/demo/apps/tables/views.py +++ b/demo/apps/tables/views.py @@ -1,19 +1,21 @@ #coding=utf-8 from uliweb import expose, functions -from json import dumps @expose('/tables') class Tables(object): @expose('') def list(self): table_keys = settings.APIJSON_MODELS.keys() - if request.user and functions.has_role(request.user,"ADMIN"): - role = "ADMIN" - elif request.user: - role = "LOGIN" + if request.user: + if functions.has_role(request.user,"ADMIN"): + role = "ADMIN" + else: + role = "OWNER" else: role = "UNKNOWN" + apijson_tables = functions.get_apijson_tables(role) return { - "table_keys_json":dumps(table_keys), - "role":role + "table_keys_json":json_dumps(table_keys), + "apijson_tables_json":json_dumps(apijson_tables), + "role":role, } diff --git a/uliweb_apijson/apijson/__init__.py b/uliweb_apijson/apijson/__init__.py index e69de29..130a65a 100644 --- a/uliweb_apijson/apijson/__init__.py +++ b/uliweb_apijson/apijson/__init__.py @@ -0,0 +1,17 @@ +#coding=utf-8 + +def get_apijson_tables(role="UNKNOWN"): + from uliweb import settings + apijson_tables = dict(settings.APIJSON_TABLES.iteritems()) + for n in apijson_tables: + c = apijson_tables[n] + editable = c["editable"] + if editable=="auto": + editable = False + POST = settings.APIJSON_MODELS[n]["POST"] + if POST: + roles = POST["roles"] + if roles: + editable = role in roles + c["editable"] = editable + return apijson_tables diff --git a/uliweb_apijson/apijson/settings.ini b/uliweb_apijson/apijson/settings.ini index badc16c..d15caa2 100644 --- a/uliweb_apijson/apijson/settings.ini +++ b/uliweb_apijson/apijson/settings.ini @@ -16,3 +16,6 @@ user = { "PUT" : { "roles" : ["ADMIN","OWNER"] }, "DELETE" : { "roles" : ["ADMIN","OWNER"] }, } + +[FUNCTIONS] +get_apijson_tables = "uliweb_apijson.apijson.get_apijson_tables" diff --git a/uliweb_apijson/apijson/templates/vue/inc_apijson_table.html b/uliweb_apijson/apijson/templates/vue/inc_apijson_table.html index 2ed75a6..dad498d 100644 --- a/uliweb_apijson/apijson/templates/vue/inc_apijson_table.html +++ b/uliweb_apijson/apijson/templates/vue/inc_apijson_table.html @@ -1,15 +1,19 @@ > Vue.component('apijson-table', { delimiters: ['{', '}'], - props: ["table_name"], + props: ["table_name","config"], template: `
- + - - - + + + + + + + Save @@ -21,12 +25,17 @@ var thisp = this return { modal_view: false, - view_items: [], + viewedit_items: [], + + edit_params: {}, + modal_delete: false, - delete_params:{}, - tcolumns: [ - {title:'#',key:'id',width:80}, - { + delete_params: {}, + + tcolumns: [], + tcolumns_preset: { + "id": {title:'#',key:'id',width:80}, + "action": { title: 'Action', width: 140, render: (h, params) => { @@ -44,7 +53,7 @@ thisp.show(params) } } - }, 'View'), + }, this.viewedit_label), h('Button', { props: { type: 'error', @@ -59,16 +68,23 @@ ]); } } - ], + }, tcolumns_init: false, tlist:[], query_count: 10, current_page: 1, total: 0, sort_key: "id", - sort_order: "-" + sort_order: "-", + + config_editable: false, + config_table_fields: null, + config_viewedit_fields: null } }, + computed: { + viewedit_label: function(){return this.config_editable?'Edit':'View'} + }, methods: { update_list: function(){ var thisp = this @@ -94,21 +110,30 @@ if (data.code==200) { var arr = data["[]"] if (!thisp.tcolumns_init) { - if (arr.length>0) { - var item = arr[0] - for (var k in item){ - if (k!="id") { - var col = {title:k,key:k} - if (typeof item[k] ==="boolean") { - col["width"] = 80 - } - else if (typeof item[k] ==="number") { - col["width"] = 100 + if (thisp.config_table_fields!=null){ + thisp.tcolumns = thisp.config_table_fields + thisp.tcolumns.push(thisp.tcolumns_preset["action"]) + thisp.tcolumns_init = true + } + else { + thisp.tcolumns.push(thisp.tcolumns_preset["id"]) + if (arr.length>0) { + var item = arr[0] + for (var k in item){ + if (k!="id") { + var col = {title:k,key:k} + if (typeof item[k] ==="boolean") { + col["width"] = 80 + } + else if (typeof item[k] ==="number") { + col["width"] = 100 + } + thisp.tcolumns.push(col) } - thisp.tcolumns.push(col) } + thisp.tcolumns.push(thisp.tcolumns_preset["action"]) + thisp.tcolumns_init = true } - thisp.tcolumns_init = true } } thisp.tlist = arr @@ -119,20 +144,82 @@ }, show: function(params){ var row = params.row - this.view_items = [] - this.view_items.push({key:"id",value:row.id}) - for (var k in row){ - if (k!="id" && k[0]!="_") { - value = row[k] - this.view_items.push({key:k,value:value}) + this.viewedit_items = [] + if (this.config_viewedit_fields!=null) { + for (var i in this.config_viewedit_fields) { + var d = this.config_viewedit_fields[i] + d.value = row[d.key] + d.type = d.type || "input" + this.viewedit_items.push(d) } } + else { + this.viewedit_items.push({title:"id",value:row.id,"type":"input"}) + var type2type = { + "boolean":"checkbox" + } + for (var k in row){ + if (k!="id" && k[0]!="_") { + var value = row[k] + var type = type2type[typeof value] || "input" + this.viewedit_items.push({title:k,value:value,type:type}) + } + } + } + if (this.config_editable){ + this.edit_params = params + } + else { + this.edit_params = null + } this.modal_view = true }, + editable: function(item){ + var editable = true + if (item.editable!=null) {editable=item.editable} + return this.config_editable && editable && (item.key!="id") + }, remove: function(params){ this.delete_params = params this.modal_delete = true }, + save: function(){ + var thisp = this + var params = { + "@tag": thisp.table_name + } + var record_params = {} + var row = thisp.edit_params.row + + for (var k in thisp.viewedit_items) { + var d = thisp.viewedit_items[k] + if (d.key=="id"|| d.value!=row[d.key]) { + record_params[d.key] = d.value + } + } + params[thisp.table_name] = record_params + $.ajax({ + type: "POST", + url: "{{=url_for('uliweb_apijson.apijson.views.ApiJson.put')}}", + contentType: 'application/json', + data: JSON.stringify(params), + success: function (data) { + if (data.code==200){ + thisp.$Notice.success({ + title: 'success update #'+row.id+' in table '+thisp.table_name, + desc: data.msg + }) + thisp.update_list() + } + else { + thisp.$Notice.error({ + title: 'error when update #'+row.id+' in table '+thisp.table_name, + desc: data.msg + }) + } + } + }) + }, real_remove: function(){ var thisp = this var params = { @@ -183,6 +270,11 @@ } }, mounted: function(){ + if (this.config!=null){ + this.config_editable = this.config.editable || false + this.config_table_fields = this.config.table_fields || null + this.config_viewedit_fields = this.config.viewedit_fields || null + } this.update_list() } }) diff --git a/uliweb_apijson/apijson/views.py b/uliweb_apijson/apijson/views.py index 5dd17f7..29d2ccc 100644 --- a/uliweb_apijson/apijson/views.py +++ b/uliweb_apijson/apijson/views.py @@ -499,14 +499,14 @@ def _put_one(self,key,tag): obj_dict = {"id":id_} if ret: obj_dict["code"] = 200 - obj_dict["message"] = "success" + obj_dict["msg"] = "success" obj_dict["count"] = 1 else: obj_dict["code"] = 400 - obj_dict["message"] = "fail" + obj_dict["msg"] = "failed when updating, maybe no change" obj_dict["count"] = 0 self.rdict["code"] = 400 - self.rdict["message"] = "fail" + self.rdict["msg"] = "failed when updating, maybe no change" self.rdict[key] = obj_dict def delete(self): From 9a55c69f051c39b3344fcce408cc92c945b09863 Mon Sep 17 00:00:00 2001 From: Chunlin Zhang Date: 2019年1月18日 18:38:25 +0800 Subject: [PATCH 2/2] when not editable, not show 'delete' button --- .../templates/vue/inc_apijson_table.html | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/uliweb_apijson/apijson/templates/vue/inc_apijson_table.html b/uliweb_apijson/apijson/templates/vue/inc_apijson_table.html index dad498d..a7c1531 100644 --- a/uliweb_apijson/apijson/templates/vue/inc_apijson_table.html +++ b/uliweb_apijson/apijson/templates/vue/inc_apijson_table.html @@ -38,8 +38,19 @@ "action": { title: 'Action', width: 140, - render: (h, params) => { - return h('div', [ + render: function(h, params){ + var delete_button = h('Button', { + props: { + type: 'error', + size: 'small' + }, + on: { + click: function(){ + thisp.remove(params) + } + } + }, 'Delete') + var buttons = [ h('Button', { props: { type: 'primary', @@ -53,19 +64,12 @@ thisp.show(params) } } - }, this.viewedit_label), - h('Button', { - props: { - type: 'error', - size: 'small' - }, - on: { - click: function(){ - thisp.remove(params) - } - } - }, 'Delete') - ]); + }, thisp.viewedit_label) + ] + if (thisp.config_editable) { + buttons.push(delete_button) + } + return h('div', buttons); } } },

AltStyle によって変換されたページ (->オリジナル) /