1. perabaikan fungsi allow_check untuk menampilkan checkbox pada sisi kiri datatabale

2. Pnambahan paramater list_view_field menampilkan url view pada kolom/field yang diperlukan
3. Penambahan default sort menajdi column[0] desc
4.Penambahan defalt tombol edit dan delete pada saat view data
1 parent 93a1f9f9
......@@ -17,7 +17,7 @@ from sqlalchemy import Table
from opensipkd.tools import dmy, get_settings, get_ext, \
date_from_str, get_random_string, Upload, InvalidExtension, mem_tmp_store
from opensipkd.tools.buttons import (
btn_save, btn_cancel, btn_close, btn_delete, btn_add, btn_csv,
btn_save, btn_cancel, btn_close, btn_delete, btn_add, btn_csv, btn_edit,
btn_pdf, btn_upload)
# from opensipkd.tools.captcha import get_captcha
from opensipkd.tools.report import csv_response, file_response
......@@ -48,6 +48,8 @@ class CSRFSchema(colander.Schema):
widget=widget_os.CSRFWidget(),
)
from pyramid.interfaces import IRoutesMapper
from pyramid.threadlocal import get_current_registry
class BaseView(object):
def __init__(self, request):
......@@ -76,6 +78,7 @@ class BaseView(object):
self.list_report = (btn_csv, btn_pdf)
self.list_buttons = (btn_add,)
self.list_upload = (btn_upload,)
self.list_view_field = None
self.columns = None
# self.form_params = dict(scripts="")
self.list_url = ""
......@@ -106,9 +109,21 @@ class BaseView(object):
});"""
self.form_widget = None
# self.list_schema = colander.Schema()
self.add_schema = colander.Schema()
# self.edit_schema = colander.Schema()
self.list_schema = colander.Schema(
error=colander.SchemaNode(
colander.String, title="Override",
missing=colander.drop,
default="Silahkan buat list schema"))
self.add_schema = colander.Schema(
error=colander.SchemaNode(
colander.String, title="Override",
missing=colander.drop,
default="Silahkan buat add schema"))
self.edit_schema = colander.Schema(
error=colander.SchemaNode(
colander.String, title="Override",
missing=colander.drop,
default="Silahkan buat schema edit"))
self.upload_schema = UploadSchema
self.upload_exts = (".csv", ".tsv")
......@@ -244,6 +259,11 @@ class BaseView(object):
pass
"""
def route_found(self, route_name):
reg = get_current_registry() # b/c
mapper = reg.getUtility(IRoutesMapper)
return mapper.get_route(route_name)
def get_routes(self):
"""
Digunakan untuk mendapatkan default url apabila list_url tidak ada
......@@ -542,10 +562,17 @@ class BaseView(object):
# log.debug(str(columns))
# qry = query.add_columns(*[c.sqla_expr for c in columns])
# log.debug(str(qry))
if self.req.params.get("order[0][column]", None):
self.req.params["order[0][column]"]='0'
self.req.params["order[0][dir]"]='desc'
row_table = DataTables(self.req.GET, query, columns)
result = row_table.output_result()
data = result and result.get("data") or {}
for res in data:
if self.list_view_field:
list_url = self.req.route_url(self.list_route)
res[self.list_view_field] = f"<a href='{list_url}/{res['id']}/view'>{res[self.list_view_field]}</a>"
for k in res:
if k in select_list.keys():
vals = select_list[k]
......@@ -639,8 +666,13 @@ class BaseView(object):
)
def view_buttons(self, row):
result = (btn_close,)
return result
result =[]
if self.route_found(self.list_route+"-edit"):
result.append(btn_edit)
if self.route_found(self.list_route+"-delete"):
result.append(btn_delete)
result.append(btn_close)
return tuple(result)
def before_view(self, **kw):
return False
......@@ -665,6 +697,19 @@ class BaseView(object):
form = self.get_form(self.edit_schema, buttons=buttons,
bindings=bindings)
if request.POST:
if 'edit' in request.POST:
return HTTPFound(
location=self.req.route_url(
self.list_route+"-edit",
id=row.id,
act='edit'))
elif 'delete' in request.POST:
return HTTPFound(
location=self.req.route_url(
self.list_route+"-delete",
id=row.id,
act='delete'))
result = self.next_view(form=form, row=row)
if result:
return result
......@@ -1065,7 +1110,22 @@ class BaseView(object):
def view_delete(self, **kwargs):
request = self.req
q = self.query_id()
if self.allow_check:
rcount = q.count()
if rcount > 1:
try:
q.delete(synchronize_session='fetch')
self.db_session.flush()
request.session.flash(f"{rcount} Data berhasil dihapus.")
except Exception as e:
request.session.flash(
f"Gagal menghapus data. "
f"Pastikan data tidak berelasi dengan data lain. "
f"Error: {str(e)}", "error")
return self.route_list()
self.ses["readonly"] = True
row = q.first()
is_object = kwargs.get("is_object", self.is_object)
......@@ -1099,6 +1159,9 @@ class BaseView(object):
def query_id(self, id_=None):
id_ = id_ or self.req.matchdict['id']
if id_=='all':
ids_ = [int(i) for i in self.req.params.get("ids").split(",")]
return self.table.query().filter(self.table.id.in_(ids_))
return self.table.query_id(id_)
# if self.req.user:
......
......@@ -160,8 +160,16 @@ class DeTable(field.Field):
}""" % (tableid, tableid, tableid, params),
"view": "{window.location = o%sUri+'/'+m%sID+'/view%s';}" % (
tableid, tableid, params),
"delete": "{window.location = o%sUri+'/'+m%sID+'/delete%s';}" % (
tableid, tableid, params),
"delete": not self.allow_check and "{window.location = o%sUri+'/'+m%sID+'/delete%s';}" % (
tableid, tableid, params) or \
"""{
var cnt = m%sCheckList.length;
if (confirm('Menghapus '+cnt+' data, pastikan data yang dipilih sudah benar!')){
ids = m%sCheckList.join(',');
window.location = o%sUri+'/all/delete?ids='+ids;
};
event.stopPropagation();
}""" % (tableid, tableid, tableid),
"csv": "{window.location = o%sUri+'/csv/act%s';}" % (
tableid, params),
"pdf": "{window.open(o%sUri+'/pdf/act%s');}" % (tableid, params),
......@@ -191,7 +199,8 @@ class DeTable(field.Field):
class="btn {button.css_class}">
{button.title} </button>\n
""")
_scripts.append(f'$("#{tableid + button.name}").click(function ()' +
if dict_buttons[button.name]:
_scripts.append(f'$("#{tableid + button.name}").click(function ()' +
dict_buttons[button.name] + ');')
if html_buttons:
......@@ -236,7 +245,7 @@ class DeTable(field.Field):
filter_scripts = ""
for f in schema:
field_index += 1
d = {'data': f.name, 'title': f.title}
d = {'data': f.name}
data = []
if hasattr(f, 'width'):
d["width"] = f.width
......
......@@ -46,41 +46,31 @@
</div>
</div>
<div tal:condition="allow_check=='true'">
<!-- <div class="row">
<div class="row">
<!--
<div class="input-group col-md-2">
<span class="input-group-addon">
<input type="checkbox" class="${tableid}checkAll"/>
</span>
<label for="${tableid}checkAll">Pilih Semua</label>
</div>
</div> -->
<script>
$(document).ready(function () {
$(document).on("click", '.${tableid}checkAll', function () {
if (this.checked) {
$(".${tableid}_check").prop("checked", true);
} else {
$(".${tableid}_check").prop("checked", false);
}
});
});
</script>
</div>
-->
</div>
<table id="${tableid}" class="table table-bordered table-hover table-condensed dataTable no-footer">
<thead>
<tr>
<tr>
<tal:block tal:repeat="child field">
<tal:block tal:condition="python:not hasattr(child, 'visible') or getattr(child, 'visible')==True">
<th
tal:condition="python:hasattr(child, 'action') and not getattr(child.condition)==False and False or True">
${child.title} </th>
<tr>
<tal:block tal:repeat="child field">
<th class="no-sort" tal:condition="child.name=='id'">
<input type="checkbox" class="${tableid}checkAll" id="${tableid}checkAll"/>
</th>
<th tal:condition="child.name!='id'">
${child.title}
</th>
</tal:block>
</tr>
</tal:block>
</tal:block>
</tr>
</thead>
<tbody></tbody>
......@@ -157,7 +147,7 @@
return '<input type="checkbox" class="${tableid}_check" checked="' + { value } + '"></input>';
}
var mtableId = "${tableid}";
for (let co in ${tableid}Columns) {
if (${tableid}Columns[co].wg_checkbox === true) {
${tableid}Columns[co].render = function (value) {
......@@ -189,37 +179,39 @@
${tableid}Columns[co].render = function (id, typ, data, setting) {
if (${tableid}Columns[co].action === false) return ""
let result = "";
if (${ allow_check }) {
<tal:block tal:condition="allow_check=='true'">
var checked = "";
if (check_field !== "") {
checked = data[check_field] !== null ? "checked" : "";
m${tableid}CheckList.push(id);
}
var mtableId = "${tableid}";
result = '<input type="checkbox" class="' + mtableId + '_check" value="' + id + '" ' + checked + ' name="' + mtableId + '_check"/>&nbsp;';
}
if (${ allow_view })
result += '<a href="${url}/' + id + '/view"><i class="fas fa-eye" aria-hidden="true" title="View"></i></a>&nbsp;';
if (${ allow_edit })
result += '<a href="${url}/' + id + '/edit"><i class="fas fa-edit" aria-hidden="true" title="Edit"></i></a>&nbsp;'
if (${ allow_delete })
result += '<a href="${url}/' + id + '/delete"><i class="fas fa-trash" aria-hidden="true" title="Delete"></i></a>';
if (${ allow_post })
result += '<a href="${url}/' + id + '/post"><i class="fas fa-signs-post" aria-hidden="true" title="Post"></i></a>';
if (${ allow_unpost })
result += '<a href="${url}/' + id + '/unpost"><i class="fas fa-delete-left" aria-hidden="true" title="Unpost"></i></a>';
result = '<input type="checkbox" class="' + mtableId + '_check" id="' + mtableId + '_check_' + id +'" value="' + id + '" ' + checked + ' name="' + mtableId + '_check"/>&nbsp;';
</tal:block>
<tal:block tal:condition="allow_check=='false'">
<tal:block tal:condition="allow_view=='true'">
result += '<a href="${url}/' + id + '/view"><i class="fas fa-eye" aria-hidden="true" title="View"></i></a>&nbsp;';
</tal:block>
<tal:block tal:condition="allow_edit=='true'">
result += '<a href="${url}/' + id + '/edit"><i class="fas fa-edit" aria-hidden="true" title="Edit"></i></a>&nbsp;'
</tal:block>
<tal:block tal:condition="allow_delete=='true'">
result += '<a href="${url}/' + id + '/delete"><i class="fas fa-trash" aria-hidden="true" title="Delete"></i></a>';
</tal:block>
<tal:block tal:condition="allow_post=='true'">
result += '<a href="${url}/' + id + '/post"><i class="fas fa-signs-post" aria-hidden="true" title="Post"></i></a>';
</tal:block>
<tal:block tal:condition="allow_post=='true'">
result += '<a href="${url}/' + id + '/unpost"><i class="fas fa-delete-left" aria-hidden="true" title="Unpost"></i></a>';
</tal:block>
</tal:block>
return result;
}
}
}
//end column definition loop
let ${tableid}Params = {};
var param_ajax = "";
var param_data = [];
......@@ -268,10 +260,97 @@
$("div.dt-footer").attr('style', 'margin-left: -7px;');
$("div.sub-foot").attr('style', 'position:unset;');
$(".dataTables_scrollBody").attr('style', 'margin-top: -10px;');
$('#${tableid} tbody').on('click', ':checkbox', function () {
if (this.checked) m${tableid}CheckList.push($(this).val());
else m${tableid}CheckList.splice(m${tableid}CheckList.indexOf($(this).val()), 1);
<tal:block tal:condition="allow_check=='true'">
//Begin Allow Check
$('#${tableid} tbody').on('click', ':checkbox', function () {
var checkboxValue = $(this).val();
if (this.checked) {
// Add to list if not already present
if (m${tableid}CheckList.indexOf(checkboxValue) === -1) {
m${tableid}CheckList.push(checkboxValue);
}
}else {
// Remove from list
var index = m${tableid}CheckList.indexOf(checkboxValue);
if (index > -1) {
m${tableid}CheckList.splice(index, 1);
}
}
console.log("Checkbox Clicked", m${tableid}CheckList);
updateCheckAllStatus();
});
$('#${tableid} tbody').on('change', ':checkbox', function () {
var checkboxValue = $(this).val();
if (this.checked) {
// Add to list if not already present
if (m${tableid}CheckList.indexOf(checkboxValue) === -1) {
m${tableid}CheckList.push(checkboxValue);
}
}else {
// Remove from list
var index = m${tableid}CheckList.indexOf(checkboxValue);
if (index > -1) {
m${tableid}CheckList.splice(index, 1);
}
}
console.log("Checkbox Changed", m${tableid}CheckList);
updateCheckAllStatus();
});
$("#${tableid}checkAll").on("click", '', function (e) {
e.stopPropagation();
if (this.checked) {
// Check all checkboxes and add all to list
$(".${tableid}_check").each(function () {
$(this).prop("checked", true);
var checkboxValue = $(this).val();
if (m${tableid}CheckList.indexOf(checkboxValue) === -1) {
m${tableid}CheckList.push(checkboxValue);
}
});
}else {
// Uncheck all checkboxes and clear list
$(".${tableid}_check").prop("checked", false);
m${tableid}CheckList = [];
}
console.log("Check All Clicked", m${tableid}CheckList);
});
// Function to update check all status based on individual checkboxes
function updateCheckAllStatus() {
var totalCheckboxes = $(".${tableid}_check").length;
var checkedCheckboxes = $(".${tableid}_check:checked").length;
if (checkedCheckboxes === 0) {
$("#${tableid}checkAll").prop("checked", false);
$("#${tableid}checkAll").prop("indeterminate", false);
}else if (checkedCheckboxes === totalCheckboxes) {
$("#${tableid}checkAll").prop("checked", true);
$("#${tableid}checkAll").prop("indeterminate", false);
}else {
$("#${tableid}checkAll").prop("checked", false);
$("#${tableid}checkAll").prop("indeterminate", true);
}
};
// Function to get selected data from checked rows
function get${tableid}SelectedData() {
var selectedData = [];
$(".${tableid}_check:checked").each(function() {
var rowData = o${tableid}.row($(this).closest('tr')).data();
if (rowData) {
selectedData.push(rowData);
}
});
return selectedData;
};
// Function to get selected IDs
function get${tableid}SelectedIds() {
return m${tableid}CheckList.slice(); // Return copy of the array
};
//End Allow Check
</tal:block>
$('#${tableid} tbody').on('click', 'tr', function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
......@@ -285,7 +364,10 @@
$(this).addClass('row_selected');
}
});
<tal:block tal:condition="filter_columns">
//Begin Filter Columns
$(".${tableid}-control-filter").on('keyup', function (e) {
var code = e.keyCode || e.which;
if (code === 13) filter_table();
......@@ -389,9 +471,12 @@
});
filter_table();
//End Filter Columns
</tal:block>
${structure:btnscripts}
${structure:filter_scripts}
});
}); // deform callback
</script>
</div>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!