Commit 91124f84 by aagusti

list simple

1 parent 6354fa0b
$(document).ready(function () {
$('#parent_nm').bind('typeahead:selected', function (obj, datum, name) {
$('#parent_id').val(datum.id);
$('#parent_kd').val(datum.kode);
console.log(datum.kode);
});
});
\ No newline at end of file
/* dataTables Customize */
table.dataTable thead {
-- background-color: #EAEAEA;
background-color: #EAEAEA;
}
table.table-hover>tbody>tr:hover {
table.table-hover > tbody > tr:hover {
background-color: #9FAFD1;
}
table.dataTable tr.even.selected td {
background-color: #B0BED9;
background-color: #B0BED9;
}
table.dataTable tr.odd.selected td {
background-color: #9FAFD1;
background-color: #9FAFD1;
}
@media only screen and (max-width: 980px) {
aside {
padding-bottom:60px;
padding-bottom: 60px;
}
}
aside span.footer-side {
position:absolute;
bottom:10px;
display:block;
text-align:center;
width:100%;
font-size:12px;
color:#c0bbb7;
position: absolute;
bottom: 10px;
display: block;
text-align: center;
width: 100%;
font-size: 12px;
color: #c0bbb7;
}
.minified aside span.footer-side {
display:none;
display: none;
}
.loading {
background:url(../img/loading.gif) left center no-repeat;
padding-left:30px !Important;
background: url(../img/loading.gif) left center no-repeat;
padding-left: 30px !Important;
}
input.tt-hint {
padding-left: 30px !Important;
}
.tab-content {
padding-top: 20px
}
.help-block {
color: #ff0000;
font-weight: bold;
}
.SmallBox p {
letter-spacing: 0.1px;
}
.SmallBox span {
letter-spacing: 0.1px;
}
.navbar-default .navbar-nav>.open>a,
.navbar-default .navbar-nav>.open>a:hover {
color: #555!important
}
#loading {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: fixed;
display: block;
opacity: 0.7;
background-color: #fff;
z-index: 1000;
text-align: center;
}
#loading-image {
display:block;
margin-top: auto;
margin-bottom: auto;
margin-left: auto;
margin-right: auto;
/*width: 10%;*/
z-index: 1000;
}
body {
background: 0 0;
background-image: url(/static/img/background.png);
background-position: center;
background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed
}
.navbar-default .navbar-nav>li>a {
color: #fff
}
.navbar-default .navbar-nav>li>a:hover {
color: #fff
}
.project-context .title-page {
font-size: 16px;
line-height: 40px;
color: #474544
}
.dataTable td {
transition: opacity 1s ease 0s
}
body,
html {
overflow-x: hidden
}
.well {
background-color: #fff
}
#header {
background-image: none!important;
background-color: #57889c!important;
box-shadow: none!important;
border: 0!important;
height:auto !important;
}
.container {
height: 100%
}
.fixed-navigation nav>ul {
height: auto
}
#header #logo-group {
padding: 2px 5px
}
#header #logo-group #logo {
margin: 0
}
#header #logo-group #logo img {
height: 44px;
width: auto;
margin: 0
}
.project-context .title-page {
font-weight: 400;
color: #fff
}
#header .header-dropdown-list a.dropdown-toggle,
.project-context .label,
.project-context .project-selector {
color: #fff
}
.project-context .label {
text-shadow: none
}
#header #fullscreen a,
#header #hide-menu a {
background-image: none;
background-color: #fff;
border: 0;
color:#222;
}
.alert {
border-left-width: 0
}
.btn-primary {
background-color: #57889c!important;
color: #fff!important;
border: 0
}
.btn-default {
background-color: #e6e6e6!important;
color: #676767!important;
border: 0
}
.alert-info,
.btn-info {
background-color: #1956af!important;
color: #fff!important
}
.alert-success,
.btn-success {
background-color: #00a65a!important;
color: #fff!important
}
.alert-warning,
.btn-warning {
background-color: #f39c12!important;
color: #fff!important
}
.alert-danger,
.btn-danger {
background-color: #dd4b39!important;
color: #fff!important
}
.btn {
border: 0!important
}
.help-block {
color: #f30303!important
}
nav ul li a i {
width: 24px!important
}
@media only screen and (max-width:768px) {
#header #fullscreen a,
#header #hide-menu a {
background-image: none;
background-color: rgba(255, 255, 255, 0);
border: 0
}
#hide-menu i {
color: #fff!important
}
}
.btn,
a:link,
button {
-webkit-tap-highlight-color: rgba(87, 136, 156, .5)
}
.panel {
border: 1px solid #ddd!important
}
.panel-danger {
border-color: #dd4b39
}
.panel-success {
border-color: #00a65a
}
.panel-info {
/*border-color: #1956af*/
border-color: #57889c
}
.panel-warning {
border-color: #f39c12
}
.panel-danger>.panel-heading {
color: #fff;
background-color: #dd4b39;
border-color: #dd4b39
}
.panel-success>.panel-heading {
color: #fff;
background-color: #00a65a;
border-color: #00a65a
}
.panel-info>.panel-heading {
color: #fff;
/*background-color: #1956af;*/
background-color: #57889c;
border-color: #57889c
/*border-color: #1956af*/
}
.panel-warning>.panel-heading {
color: #fff;
background-color: #f39c12;
border-color: #f39c12
}
table.dataTable tr.selected td {
background-color: #9fafd1
}
:fullscreen #fullscreen>:first-child>a {
color: #6d6a69
}
.select2-selection__rendered {
padding-left: 0
}
.select2-selection--single {
height: 32px!important;
border-radius: 0!important;
border: 1px solid #ccc!important
}
div.toolbar::after {
content: "\0020";
width:100vw;
display:block;
clear:both;
}
div.dataTables_length select,
div.dataTables_filter input {
display:inline;
}
div.dataTables_filter label {
margin-bottom:0px;
}
div.dataTables_length label {
margin-bottom:0px;
}
.dataTables_wrapper {
overflow-x:scroll !important;
}
.col-lg-1, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-md-1, .col-md-10, .col-md-11, .col-md-12, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-sm-1, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-xs-1, .col-xs-10, .col-xs-11, .col-xs-12, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9 {
padding-left:7px;
padding-right:7px;
}
input.tt-hint {
padding-left:30px !Important;
.dataTables_length {
margin-left:6px;
}
.tab-content { padding-top:20px }
.help-block { color: #ff0000; font-weight: bold; }
.SmallBox p { letter-spacing: 0.1px; }
.SmallBox span { letter-spacing: 0.1px; }
\ No newline at end of file
.ui-autocomplete-loading {
padding-right:10px;
background: url("../img/loading.gif") right 10px center no-repeat !important;
}
.ui-autocomplete {
max-height: 200px;
overflow-y: auto;
overflow-x: hidden;
}
.panel-body {
margin: 0 auto !important;
}
.col-md-5 {
padding: 0px 15px !important;
}
form.form-horizontal {
padding: 0 !important;
}
div.col-md-6 {
padding-right: 12px !important;
padding-left: 15px !important;
}
.twitter-typeahead .tt-query,
.twitter-typeahead .tt-hint {
padding: .25rem .5rem !important;
line-height: normal;
font-size: 12px;
border-radius: 0 !important;
}
.form-control{
font-size:10px !important;
height: 26px;
padding: 3px 6px;
margin-bottom: 1px !important;
}
.form-control-static {
border: 1px solid #ccc;
padding: 6px 6px;
height: 26px;
background-color: #ccc;
font-size: 10px;
margin-bottom: 1px;
}
.control-label{
font-size:10px !important;
padding: 3px 6px!important;
margin-top: 1px !important;
margin-bottom: 1px !important;
}
.help-block{
font-size:10px !important;
padding: 1px 1px !important;
}
.input-group-addon {
padding: 3px 3px !important;
font-size: 10px !important;
}
.input-group-addon:first-child {
padding: 3px 3px !important;
font-size: 10px !important;
}
.input-group {
padding: 3px 3px 7px !important;
font-size: 10px !important;
}
.form-group {
text-align: left;
margin-top:5px !important;
margin-bottom:5px !important;
}
.dataTables_filter .input-group-addon{
width: 32px !important;
margin-top: 0 !important;
float: left !important;
height: 26px !important;
padding-top: 4px !important;
}
.fc-border-separate thead tr, .table thead tr {
font-size:10px !important;
}
.twitter-typeahead{
font-size: 10px !important;
margin-bottom: 0;
width: 100%;
height: 26px;
position: absolute;
top: 0;
left: 0;
z-index:2;
}
.twitter-typeahead .tt-query, .twitter-typeahead .tt-hint {
font-size: 10px !important;
margin-bottom: 0;
width: 100%;
height: 26px;
position: absolute;
top: 0;
left: 0;
z-index:2;
}
.table-responsive {
overflow-x: hidden !important;
}
.dataTables_wrapper {
overflow-x: hidden !important;
}
.dataTables_filter{
margin-left: -8px !important;
}
.table tbody tr td {
font-size: 10px;
}
.span-new {
border-left: 0;
margin: -5px;
border: -12px;
padding: 7px !important;
}
.form-horizontal .checkbox, .form-horizontal .radio {
padding: 0px;
}
.checkbox, .radio {
position: relative;
display: block;
margin-top: 3px;
margin-bottom: 3px;
}
.form-tutup {
margin-left: 5px;
}
.footer-me {
padding-top: -16px;
margin-top: 4px;
}
.alert-success {
margin-bottom: 5px;
margin-left: 8px;
margin-right: 8px;
}
.alert-danger {
margin-bottom: 5px;
margin-left: 8px;
margin-right: 8px;
}
.twitter-typeahead .tt-query, .twitter-typeahead .tt-hint {
font-size: 10px !important;
}
.disabled {
color:
#000;
}
.checkbox label, .radio label {
font-size: 10px !important;
}
input[type="checkbox"], input[type="radio"] {
margin-top: 1px !important;
}
.list-group, .list-group-item {
font-size: 10px !important;
padding: 6px 15px !important;
}
function showError(msg) {
$("#success").css('display', 'none', 'important');
$("#errors").css('display', 'box', 'important');
$("#errors").html("<span class='glyphicon glyphicon-remove'></span> " + msg);
console.log(msg);
};
function showSuccess(msg) {
$("#errors").css('display', 'none', 'important');
$("#success").css('display', 'box', 'important');
$("#success").html("<span class='glyphicon glyphicon-ok'></span> " + msg);
};
$(function () {
var current = location.pathname;
$('nav li a').each(function () {
var $this = $(this);
if ($this.attr('href') != '' && $this.attr('href') != '#') {
if ($this.attr('href') == current) {
$this.parent().addClass('active');
var ul_parent = $this.parents('ul');
ul_parent.show();
ul_parent.parents('li').addClass('open');
}
}
})
});
$(document).ready(function () {
// DO NOT REMOVE : GLOBAL FUNCTIONS!
pageSetUp();
/*
* PAGE RELATED SCRIPTS
*/
});
function number_format(number, decimals, dec_point, thousands_sep) {
// Strip all characters but numerical ones.
number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
var n = !isFinite(+number) ? 0 : +number,
prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
s = '',
toFixedFix = function (n, prec) {
var k = Math.pow(10, prec);
return '' + Math.round(n * k) / k;
};
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
import os
import re
from datetime import datetime
from datatables import ColumnDT
from dateutil.relativedelta import relativedelta
from opensipkd.tools.captcha import get_captcha
from pyramid.httpexceptions import HTTPFound
from .common import DataTables
from .. import DBSession, get_params
from opensipkd.tools import dmy, dmy_to_date, get_settings, get_ext
import colander
from deform import (widget, Form, ValidationFailure, )
from email.utils import parseaddr
from opensipkd.tools.buttons import btn_save, btn_cancel, btn_close, btn_delete
from opensipkd.tools.buttons import btn_save, btn_cancel, btn_close, btn_delete, btn_view, btn_add, btn_edit, btn_csv, \
btn_pdf
from ..models import User
from ...detable import DeTable
class BaseView(object):
......@@ -102,11 +107,14 @@ class BaseView(object):
self.list_route = 'home'
self.list_col_defs = ""
self.list_cols = ""
self.list_buttons = 'btn_view, btn_add, btn_edit, btn_delete, ' \
'btn_close'
# self.list_buttons = 'btn_view, btn_add, btn_edit, btn_delete, ' \
# 'btn_close'
self.list_report = (btn_csv, btn_pdf)
self.list_buttons = (btn_view, btn_add, btn_edit, btn_delete, btn_close)
self.form_params = dict(scripts="")
self.list_url = ''
self.list_route = ''
self.list_schema = ""
self.form_scripts = """
$('#parent_nm').bind('typeahead:selected', function(obj, datum) {
$('#parent_id').val(datum.id);
......@@ -121,7 +129,9 @@ class BaseView(object):
self.headers = None
self.bindings = {}
self.autocomplete = 'on'
# self.captcha = ""
def delete_msg(self, row):
return f'Data ID {row.id} sudah dihapus.'
def route_list(self, msg=None, error=""):
if msg:
......@@ -139,8 +149,8 @@ class BaseView(object):
def get_form(self, class_form, row=None, buttons=(btn_save, btn_cancel), **bindings):
buttons = self.buttons and self.buttons or buttons
bindings = self.bindings and self.bindings or bindings
schema = class_form(validator=self.form_validator) #
bindings = self.bindings and self.bindings or self.get_bindings()
schema = class_form(validator=self.form_validator)
schema = schema.bind(request=self.req, **bindings)
schema.request = self.req
if row:
......@@ -153,18 +163,28 @@ class BaseView(object):
return r
def view_list(self, arg=None):
arg = not arg and {} or arg
if self.list_schema:
table = DeTable(self.list_schema(), action=self.req.route_url(self.list_route),
action_suffix="/grid/act",
buttons=self.list_buttons)
resources = table.get_widget_resources()
return dict(form=table.render(), scripts="", css=resources["css"], js=resources["js"])
arg = arg and arg or {}
arg.update(url=self.list_url, col_defs=self.list_col_defs,
cols=self.list_cols, buttons=self.list_buttons)
return arg
def get_bindings(self, row=None):
return {}
def view_view(self): # row = query_id(request).first()
request = self.req
row = self.query_id().first()
if not row:
return self.id_not_found()
bindings = hasattr(self, "get_bindings") and self.get_bindings() or None
form = self.get_form(self.edit_schema, buttons=(btn_close,), bindings=bindings)
bindings = self.get_bindings(row)
form = self.get_form(self.edit_schema, buttons=(btn_close,), **bindings)
if request.POST:
return self.route_list()
......@@ -174,15 +194,52 @@ class BaseView(object):
scripts=self.form_scripts)
def before_add(self):
return
return {}
def validation_failure(self, value):
return value
def cancel_act(self):
pass
def after_add(self, row, values):
return
def next_act(self):
return
def list_join(self, query):
return query
def view_act(self):
url_dict = self.req.matchdict
if url_dict['act'] == 'grid':
columns = []
for d in self.list_schema():
global_search = hasattr(d, "searchable") and hasattr(d, "searchable") == False and False or True
if hasattr(d, "field"):
if type(d.field) == str:
columns.append(
ColumnDT(getattr(self.table, d.field), mData=d.name, global_search=global_search))
else:
columns.append(ColumnDT(d.field, mData=d.name))
else:
columns.append(ColumnDT(getattr(self.table, d.name), mData=d.name))
query = DBSession.query().select_from(self.table)
query = self.list_join(query)
if self.req.user.company_id and hasattr(self.table, "company_id"):
query = query.filter(self.table.company_id == self.req.user.company_id)
row_table = DataTables(self.req.GET, query, columns)
return row_table.output_result()
else:
self.next_act()
def view_add(self):
form = self.get_form(self.add_schema)
bindings = self.get_bindings()
form = self.get_form(self.add_schema, **bindings)
table = self.get_item_table()
resources = form.get_widget_resources()
if self.req.POST:
if 'save' in self.req.POST:
controls = self.req.POST.items()
......@@ -192,17 +249,19 @@ class BaseView(object):
value = self.validation_failure(e.cstruct)
value.update(self.before_add())
form.render(appstruct=value)
return dict(form=form.render(), scripts=self.form_scripts)
self.save_request(dict(controls))
return dict(form=form.render(), table=table and table.render() or None,
scripts=self.form_scripts, css=resources["css"], js=resources["js"])
values = dict(controls)
row = self.save_request(values)
self.after_add(row, values)
if "cancel" in self.req.POST or 'batal' in self.req.POST:
self.cancel_act()
return self.route_list()
values = self.before_add()
form.set_appstruct(values)
table = self.get_item_table()
return dict(form=form.render(), table=table and table.render() or None,
scripts=self.form_scripts)
scripts=self.form_scripts, css=resources["css"], js=resources["js"])
def before_save(self, row, values):
return row
......@@ -230,9 +289,9 @@ class BaseView(object):
def save_request(self, values, row=None):
params = self.req.params
for p in params:
values[p] = params[p]
for k, v in params.items():
if v:
values[k] = v
return self.save(values, self.req.user, row)
def id_not_found(self):
......@@ -262,7 +321,11 @@ class BaseView(object):
row = self.query_id().first()
if not row:
return self.id_not_found()
if not self.bindings:
self.bindings = self.get_bindings(row)
form = self.get_form(self.edit_schema)
table = self.get_item_table(row)
resources = form.get_widget_resources()
if request.POST:
if 'save' in request.POST:
controls = request.POST.items()
......@@ -270,15 +333,19 @@ class BaseView(object):
controls = form.validate(controls)
except ValidationFailure as e:
form.set_appstruct(e.cstruct)
return dict(form=form.render(), scripts=self.form_scripts)
return dict(form=form.render(), table=table and table.render() or None,
scripts=self.form_scripts, css=resources["css"], js=resources["js"])
self.save_request(dict(controls), row)
return self.route_list()
values = self.get_values(row)
form.set_appstruct(values)
form = self.before_edit(form)
table = self.get_item_table(row)
return dict(form=form.render(), table=table and table.render() or None, scripts=self.form_scripts)
return dict(form=form.render(), table=table and table.render() or None,
scripts=self.form_scripts, css=resources["css"], js=resources["js"])
def before_delete(self, row):
pass
def view_delete(self):
request = self.req
......@@ -288,15 +355,18 @@ class BaseView(object):
return self.id_not_found()
if request.POST:
if 'delete' in request.POST:
msg = f'Data ID {row.id} sudah dihapus.'
msg = self.delete_msg(row)
self.before_delete(row)
q.delete()
DBSession.flush()
request.session.flash(msg)
return self.route_list()
form = self.get_form(self.edit_schema, buttons=(btn_delete, btn_cancel))
form.set_appstruct(self.get_values(row))
table = self.get_item_table(row)
return dict(form=form.render(), table=table and table.render() or None, scripts=self.form_scripts)
resources = form.get_widget_resources()
form.set_appstruct(self.get_values(row))
return dict(form=form.render(readonly=True), table=table and table.render() or None,
scripts=self.form_scripts, css=resources["css"], js=resources["js"])
def query_id(self):
q = DBSession.query(self.table).filter_by(
......@@ -305,6 +375,11 @@ class BaseView(object):
q = q.filter_by(company_id=self.req.user.company_id)
return q
def filter_company(self, query):
if self.req.user.company_id:
return query.filter(self.table.company_id == self.req.user.company_id)
return query
@colander.deferred
def deferred_status(node, kw):
......@@ -346,6 +421,7 @@ def need_captcha():
is_captcha = get_params("reg_captcha")
return is_captcha == '1' or is_captcha == "True" or is_captcha == "true" or is_captcha == True
def need_verify():
result = get_params("reg_verify")
return result == '1' or result == "True" or result == "true" or result == True
......
......@@ -50,7 +50,7 @@ class ViewCompany(BaseView):
self.list_buttons = 'btn_view, btn_add, btn_edit, btn_delete, ' \
'btn_close'
self.form_params = dict(scripts="")
self.list_url = 'company'
# self.list_url = 'company'
self.list_route = 'company'
self.add_schema = AddSchema
self.edit_schema = EditSchema
......
import json
import colander
from deform import (widget, Form, )
from opensipkd.tools.buttons import btn_close, btn_cancel, btn_save, btn_add, btn_edit, btn_delete
from deform import (widget, )
from pyramid.view import (view_config, )
from . import widget_os
from opensipkd.detable import DeTable
from .provinsi import provinsi_widget
from ..models import DBSession, ResDati2, kategori_dati2, ResProvinsi
from ..views import ColumnDT, DataTables, BaseView
......@@ -51,7 +47,7 @@ class ListSchema(colander.Schema):
kode = colander.SchemaNode(colander.String(), width='100pt', title="Kode")
nama = colander.SchemaNode(colander.String(), title="Nama")
provinsi = colander.SchemaNode(colander.String())
status = colander.SchemaNode(colander.Integer(),width="30pt")
status = colander.SchemaNode(colander.Integer(), width="30pt")
class ViewDati2(BaseView):
......@@ -64,6 +60,7 @@ class ViewDati2(BaseView):
self.add_schema = AddSchema
self.edit_schema = EditSchema
self.table = ResDati2
self.list_schema = ListSchema
########
# List #
......@@ -103,43 +100,20 @@ class ViewDati2(BaseView):
elif found:
err_nama()
def get_form(self, class_form, row=None, buttons=(btn_save, btn_cancel)):
schema = class_form(validator=self.form_validator)
schema = schema.bind(request=self.req,
provinsi_list=ResProvinsi.get_list())
schema.request = self.req
if row:
schema.deserialize(row)
return Form(schema, buttons=buttons)
def get_bindings(self, row=None):
return dict(request=self.req,
provinsi_list=ResProvinsi.get_list())
@view_config(route_name='dati2',
renderer='templates/form_input.pt',
renderer='templates/table.pt',
permission='dati2')
def view_list(self):
table = DeTable(ListSchema(title="Kabupaten/Kota"), action=f"{self.home}/dati2",
buttons=(btn_close, btn_add, btn_edit, btn_delete))
return dict(form=table.render(), scripts=self.form_scripts)
return super(ViewDati2, self).view_list()
@view_config(route_name='dati2-view',
renderer='templates/form_input.pt', permission='dati2')
renderer='templates/form.pt', permission='dati2')
def view_view(self): # row = query_id(request).first()
request = self.req
row = self.query_id().first()
if not row:
return self.id_not_found()
form = self.get_form(EditSchema, buttons=(btn_close,))
if request.POST:
return self.route_list()
form.set_appstruct(self.get_values(row))
return dict(form=form.render(readonly=True), scripts=self.form_scripts)
# @view_config(route_name='dati2',
# renderer='templates/list.pt',
# permission='dati2')
# def view_list(self):
# return super().viewlist()
return super(ViewDati2, self).view_view()
@view_config(route_name='dati2-act', renderer='json',
permission='view')
......@@ -175,9 +149,6 @@ class ViewDati2(BaseView):
def view_edt(self):
return super(ViewDati2, self).view_edit()
##########
# Delete
##########
@view_config(route_name='dati2-delete',
renderer='templates/form_input.pt', permission='dati2')
def view_delete(self):
......
import csv
import json
import os
import shutil
from datetime import datetime
import colander
from deform import (Form, widget, ValidationFailure, )
from deform import (widget, )
from deform.widget import AutocompleteInputWidget
from pyramid.httpexceptions import (HTTPFound, )
from opensipkd.tools import (get_ext, get_random_string, get_settings)
from pyramid.view import (view_config, )
from sqlalchemy import func
from sqlalchemy.orm import aliased
from opensipkd.tools import (get_ext, get_random_string, get_settings)
from opensipkd.tools.buttons import btn_cancel, btn_save, btn_delete, btn_close
from .company import company_widget
from .upload import AddSchema as UploadSchema
from .. import renderer
from ..models import DBSession, Departemen, Partner, PartnerDepartemen, ResCompany
from ..models import DBSession, Departemen, Partner, PartnerDepartemen
from ..views import ColumnDT, DataTables, BaseView
SESS_ADD_FAILED = 'Tambah departemen gagal'
......@@ -40,12 +36,20 @@ def departemen_widget(node, kw):
class AddSchema(colander.Schema):
parent_id = colander.SchemaNode(colander.Integer(),
widget=widget.HiddenWidget(), oid="parent_id", missing=colander.drop, )
parent_nm = colander.SchemaNode(colander.String(), missing=colander.drop,
widget=AutocompleteInputWidget(size=60, min_length=3, ),
oid="parent_nm", title="Induk")
parent_id = colander.SchemaNode(
colander.Integer(),
widget=widget.HiddenWidget(), oid="parent_id", missing=colander.drop,
)
parent_nm = colander.SchemaNode(
colander.String(), missing=colander.drop,
widget=widget.AutocompleteInputWidget(
size=60, min_length=3,
requirements=(("typeahead", None), ("deform", None),
{"js": "opensipkd.base:static/js/form/departemen.js"})
),
oid="parent_nm", title="Induk")
parent_kd = colander.SchemaNode(colander.String(),
widget=widget.TextInputWidget(css_class="readonly"),
missing=colander.drop, oid="parent_kd", title="Kode Induk")
......@@ -72,15 +76,22 @@ class AddSchema(colander.Schema):
def after_bind(self, schema, kwargs):
request = kwargs["request"]
self["parent_nm"] = colander.SchemaNode(colander.String(),
missing=colander.drop,
widget=AutocompleteInputWidget(size=60, min_length=3,
values=f"{request._host}/departemen/hon/act"),
oid="parent_nm",
title="Induk", )
# self["parent_nm"] = colander.SchemaNode(
# colander.String(),
# missing=colander.drop,
# widget=AutocompleteInputWidget(
# size=60, min_length=3,
# values=f"{request.route_url('departemen')}/hon/act"),
# oid="parent_nm",
# title="Induk", )
self["parent_nm"].widget = widget.AutocompleteInputWidget(
size=60, min_length=3,
requirements=(("typeahead", None), ("deform", None),
{"js": "opensipkd.base:static/js/form/departemen.js"}),
values=f"{request.route_url('departemen')}/hon/act")
if request.user.company_id:
self["company_id"].widget = widget.HiddenWidget()
self["company_id"].default = request.user.company_id
self["company_id"].default = request.user.company_id
class EditSchema(AddSchema):
......@@ -88,56 +99,43 @@ class EditSchema(AddSchema):
widget=widget.HiddenWidget(readonly=True))
class ListSchema(colander.Schema):
id = colander.SchemaNode(colander.String(), title="ID", visible=False)
kode = colander.SchemaNode(colander.String(), title="Kode", width='100pt')
nama = colander.SchemaNode(colander.String(), title="Nama")
status = colander.SchemaNode(colander.Boolean(), title="Status", width='50pt')
level_id = colander.SchemaNode(colander.String(), title="Level", width='50pt')
parent = colander.SchemaNode(colander.String(), title="Induk", width='200pt')
class ViewDepartemen(BaseView):
def __init__(self, request):
super(ViewDepartemen, self).__init__(request)
self.form_scripts = """
$(document).ready(function () {
$('#parent_nm').typeahead({
"hint" : true,
"highlight": true,
"minLength": 1,
"remote" : {
url: "/departemen/hon/act?term=%QUERY",
beforeSend: function () {
$('#parent_nm').addClass("loading");
},
filter: function(parsedResponse){
$('#parent_nm').removeClass('loading');
return parsedResponse;
}
},
},{
"name" : 'parent_nm',
"displayKey": 'value',
});
$('#parent_nm').bind('typeahead:selected', function(obj, datum, name) {
$('#parent_id').val(datum.id);
$('#parent_kd').val(datum.kode);
});
});
"""
self.list_col_defs = json.dumps(
[{"searchable": False, "visible": False, "targets": [0], }, {
"searchable": True, "orderable": True, "targets": [1, 2],
}])
self.list_cols = [{'title': "ID", 'data': "id"},
{'title': "Kode", 'data': "kode", 'width': '100pt'},
{'title': "Nama", 'data': "nama"}, ]
self.list_buttons = 'btn_view, btn_add, btn_edit, btn_delete, ' \
'btn_close'
self.form_params = dict(scripts="")
self.list_url = 'departemen'
self.list_route = 'departemen'
self.list_schema = ListSchema
self.add_schema = AddSchema
self.edit_schema = EditSchema
self.table = Departemen
# self.list_url = 'departemen'
self.list_route = 'departemen'
self.form_scripts = ""
# """
# self.list_col_defs = json.dumps(
# [{"searchable": False, "visible": False, "targets": [0], }, {
# "searchable": True, "orderable": True, "targets": [1, 2],
# }])
# self.list_cols = [{'title': "ID", 'data': "id"},
# {'title': "Kode", 'data': "kode", 'width': '100pt'},
# {'title': "Nama", 'data': "nama"}, ]
# self.list_buttons = 'btn_view, btn_add, btn_edit, btn_delete, ' \
# 'btn_close'
# self.form_params = dict(scripts="")
########
# List #
########
@staticmethod
def form_validator(form, value):
def form_validator(self, form, value):
def err_kode():
raise colander.Invalid(form, 'Kode %s sudah digunakan oleh %s' % (
value['kode'], found.nama))
......@@ -154,16 +152,22 @@ class ViewDepartemen(BaseView):
else:
current = None
found = Departemen.query_kode(value['kode']). \
filter_by(company_id=value["company_id"]).first()
found = Departemen.query_kode(value['kode'])
if "company_id" in value and value["company_id"]:
found = found.filter_by(company_id=value["company_id"]).first()
else:
found = self.filter_company(found).first()
if current:
if found and found.id != current.id:
err_kode()
elif found:
err_kode()
found = Departemen.query_nama(value['nama']). \
filter_by(company_id=value["company_id"]).first()
found = Departemen.query_nama(value['nama'])
if "company_id" in value and value["company_id"]:
found = found.filter_by(company_id=value["company_id"]).first()
else:
found = self.filter_company(found).first()
if current:
if found and found.id != current.id:
err_nama()
......@@ -178,58 +182,64 @@ class ViewDepartemen(BaseView):
if child.children:
self.update_children(child.children)
def save(self, values, user, row=None):
if not row:
row = Departemen()
row.created = datetime.now()
row.create_uid = user.id
if 'parent_id' in values and not values['parent_id']:
del values['parent_id']
row.from_dict(values)
row.updated = datetime.now()
row.update_uid = user.id
row.status = 'status' in values and values['status'] and 1 or 0
row.level_id = 1
DBSession.add(row)
DBSession.flush()
if row.parent_id:
row.level_id = (row.parent.level_id or 0) + 1
DBSession.add(row)
if row.children:
for child in row.children:
child.level_id = child.parent.level_id + 1
DBSession.add(child)
DBSession.flush()
def before_save(self, row, values):
for k, v in values.items():
if not v:
setattr(row, k, None)
return row
def save_request(self, values, row=None):
request = self.req
if 'id' in request.matchdict:
values['id'] = request.matchdict['id']
values["company_id"] = request.user.company_id
row = self.save(values, request.user, row)
request.session.flash(
"Departemen {nama} sudah disimpan.".format(nama=row.nama))
# def save(self, values, user, row=None)
# if not row:
# row = Departemen()
# row.created = datetime.now()
# row.create_uid = user.id
# if 'parent_id' in values and not values['parent_id']:
# del values['parent_id']
#
# row.from_dict(values)
# row.updated = datetime.now()
# row.update_uid = user.id
# row.status = 'status' in values and values['status'] and 1 or 0
# row.level_id = 1
# DBSession.add(row)
# DBSession.flush()
# if row.parent_id:
# row.level_id = (row.parent.level_id or 0) + 1
#
# DBSession.add(row)
# if row.children:
# for child in row.children:
# child.level_id = child.parent.level_id + 1
# DBSession.add(child)
# DBSession.flush()
#
# return row
#
# def save_request(self, values, row=None):
# request = self.req
# if 'id' in request.matchdict:
# values['id'] = request.matchdict['id']
# values["company_id"] = request.user.company_id
# row = self.save(values, request.user, row)
# request.session.flash(
# "Departemen {nama} sudah disimpan.".format(nama=row.nama))
# def route_list(self, ):
# return HTTPFound(location=self.req.route_url(self.list_route))
def get_form(self, class_form, row=None, buttons=(btn_save, btn_cancel)):
schema = class_form(validator=self.form_validator)
schema = schema.bind(request=self.req,
company_list=ResCompany.get_list())
schema.request = self.req
if row:
schema.deserialize(row)
return Form(schema, buttons=buttons)
def session_failed(self, session_name):
r = dict(form=self.req.session[session_name])
del self.req.session[session_name]
return r
# def get_form(self, class_form, row=None, buttons=(btn_save, btn_cancel)):
# schema = class_form(validator=self.form_validator)
# schema = schema.bind(request=self.req,
# company_list=ResCompany.get_list())
# schema.request = self.req
# if row:
# schema.deserialize(row)
# return Form(schema, buttons=buttons)
#
# def session_failed(self, session_name):
# r = dict(form=self.req.session[session_name])
# del self.req.session[session_name]
# return r
# def query_id(self):
# return DBSession.query(Departemen).filter_by(
......@@ -243,20 +253,21 @@ class ViewDepartemen(BaseView):
@view_config(route_name='departemen-view',
renderer='templates/form_input.pt', permission='departemen')
def view_view(self): # row = query_id(request).first()
request = self.req
row = self.query_id().first()
if not row:
return self.id_not_found()
form = self.get_form(EditSchema, buttons=(btn_close,))
if request.POST:
return self.route_list()
form.set_appstruct(self.get_values(row))
return dict(form=form.render(readonly=True), scripts=self.form_scripts)
return super(ViewDepartemen, self).view_view()
# request = self.req
# row = self.query_id().first()
# if not row:
# return self.id_not_found()
#
# form = self.get_form(EditSchema, buttons=(btn_close,))
# if request.POST:
# return self.route_list()
#
# form.set_appstruct(self.get_values(row))
# return dict(form=form.render(readonly=True), scripts=self.form_scripts)
@view_config(route_name='departemen',
renderer='templates/list.pt',
renderer='templates/table.pt',
permission='departemen')
def view_list(self):
return super().view_list()
......@@ -281,8 +292,7 @@ class ViewDepartemen(BaseView):
ColumnDT(Departemen.level_id, mData='level_id'), ]
query = DBSession.query().select_from(Departemen).outerjoin(
dep_alias, Departemen.parent_id == dep_alias.id)
if self.req.user.company_id:
query = query.filter(Departemen.company_id == self.req.user.company_id)
query = self.filter_company(query)
row_table = DataTables(request.GET, query, columns)
return row_table.output_result()
......@@ -311,8 +321,7 @@ class ViewDepartemen(BaseView):
Departemen.kode) \
.ilike('%%%s%%' % term)) \
.order_by(Departemen.nama)
if self.req.user.company_id:
q = q.filter(Departemen.company_id == self.req.user.company_id)
q = self.filter_company(q)
rows = q.all()
r = []
for k in rows:
......@@ -381,48 +390,34 @@ class ViewDepartemen(BaseView):
r.append(d)
return r
@view_config(route_name='departemen-add',
renderer='templates/form_input.pt', permission='departemen')
@view_config(route_name='departemen-add', renderer='templates/form_input.pt',
permission='departemen')
def view_add(self):
request = self.req
form = self.get_form(AddSchema)
if request.POST:
if 'save' in request.POST:
controls = request.POST.items()
try:
controls = form.validate(controls)
except ValidationFailure as e:
form.render(appstruct=e.cstruct)
return dict(form=form.render(), scripts=self.form_scripts)
self.save_request(dict(controls))
return self.route_list()
return dict(form=form.render(), scripts=self.form_scripts)
return super(ViewDepartemen, self).view_add()
########
# Edit #
########
@view_config(route_name='departemen-edit',
renderer='templates/form_input.pt', permission='departemen')
def view_edt(self):
request = self.req
row = self.query_id().first()
if not row:
return self.id_not_found()
form = self.get_form(EditSchema)
if request.POST:
if 'save' in request.POST:
controls = request.POST.items()
try:
controls = form.validate(controls)
except ValidationFailure as e:
form.set_appstruct(e.cstruct)
return dict(form=form.render(), scripts=self.form_scripts)
self.save_request(dict(controls), row)
return self.route_list()
form.set_appstruct(self.get_values(row))
return dict(form=form.render(), scripts=self.form_scripts)
def view_edit(self):
return super(ViewDepartemen, self).view_edit()
# request = self.req
# row = self.query_id().first()
# if not row:
# return self.id_not_found()
#
# form = self.get_form(EditSchema)
# if request.POST:
# if 'save' in request.POST:
# controls = request.POST.items()
# try:
# controls = form.validate(controls)
# except ValidationFailure as e:
# form.set_appstruct(e.cstruct)
# return dict(form=form.render(), scripts=self.form_scripts)
#
# self.save_request(dict(controls), row)
# return self.route_list()
# form.set_appstruct(self.get_values(row))
# return dict(form=form.render(), scripts=self.form_scripts)
##########
# Delete #
......@@ -430,22 +425,24 @@ class ViewDepartemen(BaseView):
@view_config(route_name='departemen-delete',
renderer='templates/form_input.pt', permission='departemen')
def view_delete(self):
request = self.req
q = self.query_id()
row = q.first()
if not row:
return self.id_not_found()
if request.POST:
if 'delete' in request.POST:
msg = 'Departemen ID %d %s sudah dihapus.' % (row.id, row.nama)
q.delete()
DBSession.flush()
request.session.flash(msg)
return self.route_list()
form = self.get_form(EditSchema,
buttons=(btn_delete, btn_cancel))
form.set_appstruct(self.get_values(row))
return dict(form=form.render(readonly=True), scripts=self.form_scripts)
return super(ViewDepartemen, self).view_delete()
# request = self.req
# q = self.query_id()
# row = q.first()
# if not row:
# return self.id_not_found()
# if request.POST:
# if 'delete' in request.POST:
# msg = 'Departemen ID %d %s sudah dihapus.' % (row.id, row.nama)
# q.delete()
# DBSession.flush()
# request.session.flash(msg)
# return self.route_list()
# form = self.get_form(EditSchema,
# buttons=(btn_delete, btn_cancel))
# form.set_appstruct(self.get_values(row))
# return dict(form=form.render(readonly=True), scripts=self.form_scripts)
##########
# Upload #
......@@ -507,19 +504,18 @@ class ViewDepartemen(BaseView):
values["parent_kd"] = parent.kode
return values
def save_upload(request, kode, csv_row):
row = Departemen.query_kode(kode).first()
if not row:
row = Departemen()
row.created = datetime.now()
row.create_uid = request.user.id
row.level_id = kode.count('.') + 1
row.status = 1
else:
row.updated = datetime.now()
row.update_uid = request.user.id
row.kode = kode
row.nama = csv_row['nama']
DBSession.add(row)
return row
def save_upload(self, kode, csv_row):
row = Departemen.query_kode(kode).first()
if not row:
row = Departemen()
row.created = datetime.now()
row.create_uid = self.req.user.id
row.level_id = kode.count('.') + 1
row.status = 1
else:
row.updated = datetime.now()
row.update_uid = self.req.user.id
row.kode = kode
row.nama = csv_row['nama']
DBSession.add(row)
return row
......@@ -23,8 +23,8 @@ def desa_widget(node, kw):
class AddSchema(colander.Schema):
kecamatan_id = colander.SchemaNode(colander.String(),
widget=kecamatan_widget,
validator=colander.Length(max=32), oid="kode")
widget=kecamatan_widget,
validator=colander.Length(max=32), oid="kode")
kode = colander.SchemaNode(colander.String(),
validator=colander.Length(max=32), oid="kode")
kategori = colander.SchemaNode(colander.String(),
......@@ -38,6 +38,7 @@ class EditSchema(AddSchema):
id = colander.SchemaNode(colander.String(), missing=colander.drop,
widget=widget.HiddenWidget(readonly=True))
class ListSchema(colander.Schema):
id = colander.SchemaNode(colander.Integer(), searchable=False, orderable=False, visible=False)
kode = colander.SchemaNode(colander.String(), width='100pt', title="Kode")
......@@ -45,30 +46,18 @@ class ListSchema(colander.Schema):
kecamatan = colander.SchemaNode(colander.String())
status = colander.SchemaNode(colander.Integer(), width="30pt")
class ViewDesa(BaseView):
def __init__(self, request):
super(ViewDesa, self).__init__(request)
self.form_scripts = ""
self.list_col_defs = json.dumps(
[{"searchable": False, "visible": False, "targets": [0], }, {
"searchable": True, "orderable": True, "targets": [1, 2],
}])
self.list_cols = [{'title': "ID", 'data': "id"},
{'title': "Kecamatan", 'data': "kecamatan", 'width': '200pt'},
{'title': "Kode", 'data': "kode", 'width': '100pt'},
{'title': "Nama", 'data': "nama"}, ]
self.list_buttons = 'btn_view, btn_add, btn_edit, btn_delete, ' \
'btn_close'
self.form_params = dict(scripts="")
self.list_url = 'desa'
self.list_route = 'desa'
self.add_schema = AddSchema
self.edit_schema = EditSchema
self.table = ResDesa
########
# List #
########
self.list_schema = ListSchema
def form_validator(self, form, value):
def err_kode():
......@@ -104,17 +93,13 @@ class ViewDesa(BaseView):
elif found:
err_nama()
def get_form(self, class_form, row=None, buttons=(btn_save, btn_cancel)):
schema = class_form(validator=self.form_validator)
schema = schema.bind(request=self.req,
kecamatan_list=ResKecamatan.get_list())
schema.request = self.req
if row:
schema.deserialize(row)
return Form(schema, buttons=buttons)
def get_bindings(self, row=None):
return dict(request=self.req,
kecamatan_list=ResKecamatan.get_list())
@view_config(route_name='desa-view',
renderer='templates/form_input.pt', permission='desa')
renderer='templates/form.pt', permission='desa')
def view_view(self): # row = query_id(request).first()
request = self.req
row = self.query_id().first()
......@@ -129,12 +114,10 @@ class ViewDesa(BaseView):
return dict(form=form.render(readonly=True), scripts=self.form_scripts)
@view_config(route_name='desa',
renderer='templates/form_input.pt',
renderer='templates/table.pt',
permission='desa')
def view_list(self):
table = DeTable(ListSchema(title="Desa/Kelurahan"), action=f"{self.home}/desa",
buttons=(btn_close, btn_add, btn_edit, btn_delete))
return dict(form=table.render(), scripts=self.form_scripts)
return super(ViewDesa, self).view_list()
@view_config(route_name='desa-act', renderer='json',
permission='view')
......@@ -146,7 +129,7 @@ class ViewDesa(BaseView):
ColumnDT(ResDesa.kode, mData='kode'),
ColumnDT(ResDesa.nama, mData='nama'),
ColumnDT(ResDesa.status, mData='status'),
ColumnDT(ResKecamatan.nama, mData='kecamatan'),]
ColumnDT(ResKecamatan.nama, mData='kecamatan'), ]
query = DBSession.query().select_from(ResDesa) \
.join(ResKecamatan, ResKecamatan.id == ResDesa.kecamatan_id)
row_table = DataTables(request.GET, query, columns)
......@@ -157,24 +140,17 @@ class ViewDesa(BaseView):
result = {f"{k[0]}": k[1] for k in data}
return result
@view_config(route_name='desa-add',
renderer='templates/form_input.pt', permission='desa')
renderer='templates/form.pt', permission='desa')
def view_add(self):
return super(ViewDesa, self).view_add()
########
# Edit #
########
@view_config(route_name='desa-edit',
renderer='templates/form_input.pt', permission='desa')
renderer='templates/form.pt', permission='desa')
def view_edt(self):
return super(ViewDesa, self).view_edit()
##########
# Delete
##########
@view_config(route_name='desa-delete',
renderer='templates/form_input.pt', permission='desa')
renderer='templates/form.pt', permission='desa')
def view_delete(self):
return super(ViewDesa, self).view_delete()
import os
import uuid
# from ..tools import row2dict, xls_reader
from datetime import datetime
from sqlalchemy import not_, func
from pyramid.view import (
view_config,
)
from pyramid.httpexceptions import (
HTTPFound,
)
import colander
from deform import (
Form,
widget,
ValidationFailure,
)
from ..views import ColumnDT, DataTables, BaseView
from pyramid.httpexceptions import (
HTTPFound,
)
from pyramid.view import (
view_config,
)
from ..models import (
DBSession,
Eselon
)
from ..views import ColumnDT, DataTables, BaseView
SESS_ADD_FAILED = 'Tambah eselon gagal'
SESS_EDIT_FAILED = 'Edit eselon gagal'
......@@ -33,13 +31,6 @@ class AddSchema(colander.Schema):
nama = colander.SchemaNode(
colander.String(),
oid="nama")
# eselon = colander.SchemaNode(
# colander.String(),
# oid = "eselon")
# ruang = colander.SchemaNode(
# colander.String(),
# oid = "ruang")
# edit
status = colander.SchemaNode(
colander.Boolean(),
oid="status")
......@@ -51,10 +42,7 @@ class EditSchema(AddSchema):
widget=widget.HiddenWidget())
class view_eselon(BaseView):
########
# List #
########
class Views(BaseView):
@view_config(route_name='eselon', renderer='templates/eselon/list.pt',
permission='eselon')
def view_list(self):
......
from pyramid.view import view_config
from pyramid.httpexceptions import (
HTTPFound,
HTTPNotFound,
)
from pyramid.i18n import TranslationStringFactory
import colander
from deform import (
Form,
widget,
ValidationFailure,
Button,
)
from datatables import (
ColumnDT,
DataTables,
)
from opensipkd.tools.buttons import btn_save, btn_cancel, btn_close
from deform import widget
from pyramid.httpexceptions import HTTPFound
from pyramid.i18n import TranslationStringFactory
from pyramid.view import view_config
from . import BaseView
from ..models import (
DBSession,
Group,
......@@ -27,27 +19,6 @@ from ..models import (
_ = TranslationStringFactory('user')
# class NameValidator:
# def __init__(self, group):
# self.group = group
#
# def __call__(self, node, value):
# group_name = clean_name(value)
# if self.group and self.group.group_name.lower() == group_name.lower():
# return
# q = DBSession.query(Group). \
# filter(Group.group_name.ilike(group_name))
# found = q.first()
# if not found:
# return
# data = dict(group_name=group_name, gid=found.id)
# ts = _(
# 'group-name-already-used',
# default='Group name ${group_name} already used by ID ${gid}',
# mapping=data)
# raise colander.Invalid(node, ts)
@colander.deferred
def name_validator(node, kw):
return NameValidator(kw['group'])
......@@ -67,48 +38,129 @@ class AddSchema(colander.Schema):
colander.Set(), widget=permissions_widget, title='Hak akses')
########
# List #
########
@view_config(
route_name='group', renderer='templates/group/list.pt',
permission='user-view')
def view_list(request):
return dict()
##########
# Action #
##########
@view_config(
route_name='group-act', renderer='json', permission='user-view')
def view_act(request):
params = request.params
url_dict = request.matchdict
if url_dict['act'] == 'grid':
columns = [ColumnDT(Group.id, mData="id"),
ColumnDT(Group.group_name, mData="name"),
ColumnDT(Group.description, mData="desc"),
ColumnDT(Group.member_count, mData="member")]
q = DBSession.query().select_from(Group).order_by(Group.group_name)
rowTable = DataTables(request.GET, q, columns)
return rowTable.output_result()
elif url_dict['act'] == 'hon':
term = 'term' in params and params['term'] or ''
q = DBSession.query(Group.id, Group.description).filter(
Group.description.ilike('%{}%'.format(term))). \
order_by(Group.group_name)
rows = q.all()
r = []
for k in rows:
d = dict(id=k[0], value=k[1])
r.append(d)
return r
#######
# Add #
#######
class EditSchema(AddSchema):
id = colander.SchemaNode(colander.Integer(),
widget=widget.HiddenWidget(readonly=True),
missing=colander.drop)
class ListSchema(colander.Schema):
id = colander.SchemaNode(colander.Integer(), visible=False)
group_name = colander.SchemaNode(
colander.String(), )
description = colander.SchemaNode(colander.String())
class Views(BaseView):
def __init__(self, request):
super(Views, self).__init__(request)
self.list_schema = ListSchema
self.list_route = "group"
self.table = Group
self.add_schema = AddSchema
self.edit_schema = EditSchema
def get_bindings(self, row=None):
return dict(group=row,
permissions_list=get_permissions_list())
@view_config(
route_name='group', renderer='templates/table.pt',
permission='user-view')
def view_list(self):
return super(Views, self).view_list()
@view_config(
route_name='group-act', renderer='json', permission='user-view')
def view_act(self):
params = self.params
request = self.req
url_dict = request.matchdict
if url_dict['act'] == 'grid':
columns = [ColumnDT(Group.id, mData="id"),
ColumnDT(Group.group_name, mData="group_name"),
ColumnDT(Group.description, mData="description"),
ColumnDT(Group.member_count, mData="member_count")]
q = DBSession.query().select_from(Group).order_by(Group.group_name)
row_table = DataTables(request.GET, q, columns)
return row_table.output_result()
elif url_dict['act'] == 'hon':
term = 'term' in params and params['term'] or ''
q = DBSession.query(Group.id, Group.description).filter(
Group.description.ilike('%{}%'.format(term))). \
order_by(Group.group_name)
rows = q.all()
r = []
for k in rows:
d = dict(id=k[0], value=k[1])
r.append(d)
return r
@view_config(
route_name='group-add', renderer='templates/group/add.pt',
permission='user-edit')
def view_add(self):
return super(Views, self).view_add()
def save_request(self, values, row=None):
insert = not row
row = self.save(values, self.req.user, row)
existing = group_permission_set(row)
unused = existing - values['permissions']
if unused:
q = DBSession.query(GroupPermission).filter_by(group_id=row.id). \
filter(GroupPermission.perm_name.in_(unused))
q.delete(synchronize_session=False)
new = values['permissions'] - existing
for perm_name in new:
gp = GroupPermission()
gp.group_id = row.id
gp.perm_name = perm_name
DBSession.add(gp)
data = dict(group_name=row.group_name)
if insert:
ts = _('group-added', default='{group_name} group has been added.', mapping=data)
else:
ts = _('group-updated', default='${group_name} group profile updated', mapping=data)
self.ses.flash(ts)
return row
def get_values(self, row, istime=False):
values = super(Views, self).get_values(row, istime)
values['permissions'] = group_permission_set(row)
return values
@view_config(
route_name='group-view', renderer='templates/group/edit.pt',
permission='user-view')
def view_view(self):
return super(Views, self).view_view()
@view_config(
route_name='group-edit', renderer='templates/group/edit.pt',
permission='user-edit')
def view_edit(self):
return super(Views, self).view_edit()
def delete_msg(self, row):
data = dict(group_name=row.group_name)
ts = _(
'group-deleted',
default='{group_name} group has been deleted.',
mapping=data)
self.ses.flash(ts)
@view_config(
route_name='group-delete', renderer='templates/group/delete.pt',
permission='user-edit')
def view_delete(self):
return super(Views, self).view_delete()
q.delete()
request.session.flash(ts)
return HTTPFound(location=request.route_url('group'))
def clean_name(s):
s = s.strip()
while s.find(' ') > -1:
......@@ -124,6 +176,7 @@ class NameValidator:
group_name = clean_name(value)
if self.group and self.group.group_name.lower() == group_name.lower():
return
q = DBSession.query(Group). \
filter(Group.group_name.ilike(group_name))
found = q.first()
......@@ -157,157 +210,9 @@ def get_permissions_list():
return r
def get_form(request, group=None, buttons=(btn_save, btn_cancel)):
schema = AddSchema()
schema = schema.bind(permissions_list=get_permissions_list(), group=group)
# btn_save = Button('save', _('Simpan'))
# btn_cancel = Button('cancel', _('Batal'))
# buttons = (btn_save, btn_cancel)
return Form(schema, buttons=buttons)
def insert(values):
group = Group()
group.group_name = values['group_name']
if 'description' in values:
group.description = values['description']
DBSession.add(group)
DBSession.flush()
for perm_name in values['permissions']:
gp = GroupPermission()
gp.group_id = group.id
gp.perm_name = perm_name
DBSession.add(gp)
return group
@view_config(
route_name='group-add', renderer='templates/group/add.pt',
permission='user-edit')
def view_add(request):
form = get_form(request)
if not request.POST:
return dict(form=form.render())
if 'save' not in request.POST:
return HTTPFound(location=request.route_url('group'))
items = request.POST.items()
try:
c = form.validate(items)
except ValidationFailure as e:
return dict(form=e.render())
group = insert(dict(c.items()))
data = dict(group_name=group.group_name)
ts = _(
'group-added',
default='${group_name} group has been added.',
mapping=data)
request.session.flash(ts)
return HTTPFound(location=request.route_url('group'))
########
# Edit #
########
def group_permission_set(group):
q = DBSession.query(GroupPermission).filter_by(group_id=group.id)
r = []
for gp in q:
r.append(gp.perm_name)
return set(r)
def update(group, values):
group.group_name = values['group_name']
if 'description' in values:
group.description = values['description']
DBSession.add(group)
existing = group_permission_set(group)
unused = existing - values['permissions']
if unused:
q = DBSession.query(GroupPermission).filter_by(group_id=group.id). \
filter(GroupPermission.perm_name.in_(unused))
q.delete(synchronize_session=False)
new = values['permissions'] - existing
for perm_name in new:
gp = GroupPermission()
gp.group_id = group.id
gp.perm_name = perm_name
DBSession.add(gp)
@view_config(
route_name='group-edit', renderer='templates/group/edit.pt',
permission='user-edit')
def view_edit(request):
q = DBSession.query(Group).filter_by(id=request.matchdict['id'])
group = q.first()
if not group:
return HTTPNotFound()
form = get_form(request, group)
resp = dict(title=_('Edit group'))
if not request.POST:
d = group.to_dict_without_none()
d['permissions'] = group_permission_set(group)
resp['form'] = form.render(appstruct=d)
return resp
if 'save' not in request.POST:
return HTTPFound(location=request.route_url('group'))
# resp['form'] = form.render()
items = request.POST.items()
try:
c = form.validate(items)
except ValidationFailure:
resp['form'] = form.render()
return resp
update(group, dict(c.items()))
data = dict(group_name=group.group_name)
ts = _('group-updated', default='${group_name} group profile updated', mapping=data)
request.session.flash(ts)
return HTTPFound(location=request.route_url('group'))
@view_config(
route_name='group-view', renderer='templates/group/edit.pt',
permission='user-view')
def view_VIEW(request):
q = DBSession.query(Group).filter_by(id=request.matchdict['id'])
group = q.first()
if not group:
return HTTPNotFound()
form = get_form(request, group, buttons=(btn_close,))
resp = dict(title=_('View group'))
if not request.POST:
d = group.to_dict_without_none()
d['permissions'] = group_permission_set(group)
resp['form'] = form.render(appstruct=d, readonly=True)
return resp
return HTTPFound(location=request.route_url('group'))
##########
# Delete #
##########
@view_config(
route_name='group-delete', renderer='templates/group/delete.pt',
permission='user-edit')
def view_delete(request):
q = DBSession.query(Group).filter_by(id=request.matchdict['id'])
group = q.first()
if not group:
return HTTPNotFound()
if not request.POST:
btn_delete = Button('delete', _('Delete'))
btn_cancel = Button('cancel', _('Cancel'))
buttons = (btn_delete, btn_cancel)
form = Form(colander.Schema(), buttons=buttons)
return dict(form=form.render(), row=group)
if 'delete' not in request.POST:
return HTTPFound(location=request.route_url('group'))
data = dict(group_name=group.group_name)
ts = _(
'group-deleted',
default='{group_name} group has been deleted.',
mapping=data)
q.delete()
request.session.flash(ts)
return HTTPFound(location=request.route_url('group'))
......@@ -50,30 +50,16 @@ class ListSchema(colander.Schema):
status = colander.SchemaNode(colander.Integer(), width="30pt")
class ViewDati2(BaseView):
class Views(BaseView):
def __init__(self, request):
super(ViewDati2, self).__init__(request)
self.form_scripts = ""
# self.list_col_defs = json.dumps(
# [{"searchable": False, "visible": False, "targets": [0], }, {
# "searchable": True, "orderable": True, "targets": [1, 2],
# }])
# self.list_cols = [{'title': "ID", 'data': "id"},
# {'title': "Kab/Kota", 'data': "dati2", 'width': '200pt'},
# {'title': "Kode", 'data': "kode", 'width': '100pt'},
# {'title': "Nama", 'data': "nama"}, ]
# self.list_buttons = 'btn_view, btn_add, btn_edit, btn_delete, ' \
# 'btn_close'
super(Views, self).__init__(request)
self.form_params = dict(scripts="")
self.list_url = 'kecamatan'
self.list_route = 'kecamatan'
self.add_schema = AddSchema
self.edit_schema = EditSchema
self.table = ResKecamatan
########
# List #
########
self.list_schema = ListSchema
def form_validator(self, form, value):
def err_kode():
......@@ -119,8 +105,9 @@ class ViewDati2(BaseView):
return Form(schema, buttons=buttons)
@view_config(route_name='kecamatan-view',
renderer='templates/form_input.pt', permission='kecamatan')
renderer='templates/form.pt', permission='kecamatan')
def view_view(self): # row = query_id(request).first()
request = self.req
row = self.query_id().first()
if not row:
......@@ -134,12 +121,10 @@ class ViewDati2(BaseView):
return dict(form=form.render(readonly=True), scripts=self.form_scripts)
@view_config(route_name='kecamatan',
renderer='templates/form_input.pt',
renderer='templates/table.pt',
permission='kecamatan')
def view_list(self):
table = DeTable(ListSchema(title="Kecamatan"), action=f"{self.home}/kecamatan",
buttons=(btn_close, btn_add, btn_edit, btn_delete))
return dict(form=table.render(), scripts=self.form_scripts)
return super(Views, self).view_list(self)
@view_config(route_name='kecamatan-act', renderer='json',
permission='view')
......@@ -163,22 +148,19 @@ class ViewDati2(BaseView):
return result
@view_config(route_name='kecamatan-add',
renderer='templates/form_input.pt', permission='kecamatan')
renderer='templates/form.pt', permission='kecamatan')
def view_add(self):
return super(ViewDati2, self).view_add()
return super(Views, self).view_add()
########
# Edit #
########
@view_config(route_name='kecamatan-edit',
renderer='templates/form_input.pt', permission='kecamatan')
renderer='templates/form.pt', permission='kecamatan')
def view_edt(self):
return super(ViewDati2, self).view_edit()
return super(Views, self).view_edit()
##########
# Delete
##########
@view_config(route_name='kecamatan-delete',
renderer='templates/form_input.pt', permission='kecamatan')
renderer='templates/form.pt', permission='kecamatan')
def view_delete(self):
return super(ViewDati2, self).view_delete()
return super(Views, self).view_delete()
......@@ -11,7 +11,6 @@ from sqlalchemy.orm import aliased
from . import widget_os
from ..models import DBSession, ResProvinsi, kategori_provinsi, flush
from ..views import ColumnDT, DataTables, BaseView
from ...detable import DeTable
SESS_ADD_FAILED = 'Tambah provinsi gagal'
SESS_EDIT_FAILED = 'Edit provinsi gagal'
......@@ -59,6 +58,7 @@ class ViewProvinsi(BaseView):
self.form_scripts = ""
self.form_params = dict(scripts="")
self.list_route = 'provinsi'
self.list_schema = ListSchema
self.add_schema = AddSchema
self.edit_schema = EditSchema
self.table = ResProvinsi
......@@ -100,63 +100,31 @@ class ViewProvinsi(BaseView):
err_nama()
@view_config(route_name='provinsi-view',
renderer='templates/form_input.pt', permission='provinsi')
renderer='templates/form.pt', permission='provinsi')
def view_view(self): # row = query_id(request).first()
request = self.req
row = self.query_id().first()
if not row:
return self.id_not_found()
form = self.get_form(EditSchema, buttons=(btn_close,))
if request.POST:
return self.route_list()
form.set_appstruct(self.get_values(row))
return dict(form=form.render(readonly=True), scripts=self.form_scripts)
return super(ViewProvinsi, self).view_view()
@view_config(route_name='provinsi',
renderer='templates/list_table.pt',
renderer='templates/table.pt',
permission='provinsi')
def view_list(self):
table = DeTable(ListSchema(), action=f"{self.home}/provinsi",
action_suffix="/grid/act",
buttons=(btn_view, btn_add, btn_edit, btn_delete, btn_close))
return dict(table=table.render(), scripts="")
##########
# Action #
##########
return super(ViewProvinsi, self).view_list()
@view_config(route_name='provinsi-act', renderer='json',
permission='view')
def view_act(self):
request = self.req
url_dict = request.matchdict
if url_dict['act'] == 'grid':
columns = [ColumnDT(ResProvinsi.id, mData='id'),
ColumnDT(ResProvinsi.kode, mData='kode'),
ColumnDT(ResProvinsi.nama, mData='nama'),
ColumnDT(ResProvinsi.ibu_kota, mData='ibu_kota'),
ColumnDT(ResProvinsi.status, mData='status'), ]
query = DBSession.query().select_from(ResProvinsi)
row_table = DataTables(request.GET, query, columns)
return row_table.output_result()
return super(ViewProvinsi, self).view_act()
@view_config(route_name='provinsi-add',
renderer='templates/form_input.pt', permission='provinsi')
def view_add(self):
return super(ViewProvinsi, self).view_add()
########
# Edit #
########
@view_config(route_name='provinsi-edit',
renderer='templates/form_input.pt', permission='provinsi')
def view_edt(self):
return super(ViewProvinsi, self).view_edit()
##########
# Delete
##########
@view_config(route_name='provinsi-delete',
renderer='templates/form_input.pt', permission='provinsi')
def view_delete(self):
......
# Module ini digunakan untuk registrasi user external
# Restriction dari module ini tidak boleh diubah emailnya
from email.utils import parseaddr
import colander
from deform import (Form, widget, ValidationFailure, Button)
from opensipkd.tools.api import custom_error
from opensipkd.base.views.user_login import get_login_headers
from opensipkd.base.views.user import insert as save_user
from pyramid.httpexceptions import HTTPFound
from pyramid.i18n import TranslationStringFactory
from pyramid.view import view_config
from ziggurat_foundations.models.services.user import UserService
# from . import get_login_headers
# from .register import mobile_found_partner, save_partner, nik_found
from .user_group import save as save_groups
from ..models import DBSession, Partner, Group, ExternalIdentity, User, ExternalIdentityService
from opensipkd.tools import get_settings
from opensipkd.tools.captcha import get_captcha
from ..views import BaseView
# from .user import email_validator
_ = TranslationStringFactory('user')
def email_validator(node, value):
name, email = parseaddr(value)
if not email or email.find('@') < 0:
raise colander.Invalid(node, 'Invalid email format')
class PrimarySchema(colander.Schema):
kode = colander.SchemaNode(
colander.String(),
widget=widget.TextInputWidget(),
oid="kode",
title="NIK"
)
email = colander.SchemaNode(
colander.String(),
widget=widget.TextInputWidget(readonly=True),
missing=colander.drop,
title="E-mail",
validator=email_validator,
oid="email")
class SecondarySchema(colander.Schema):
nama = colander.SchemaNode(
colander.String(),
oid="nama")
alamat_1 = colander.SchemaNode(
colander.String(),
title="Alamat",
oid="alamat_1")
alamat_2 = colander.SchemaNode(
colander.String(),
title="",
missing=colander.drop,
oid="alamat_2")
class RegSchema(colander.Schema):
primari = PrimarySchema()
mobile = colander.SchemaNode(
colander.String(),
widget=widget.TextInputWidget(),
oid="mobile")
secondari = SecondarySchema()
captcha = colander.SchemaNode(
colander.String(),
oid="captcha")
class RegEditSchema(colander.Schema):
primari = PrimarySchema()
mobile = colander.SchemaNode(
colander.String(),
widget=widget.TextInputWidget(readonly=True),
missing=colander.drop,
oid="mobile")
secondari = SecondarySchema()
id = colander.SchemaNode(
colander.Integer(),
missing=colander.drop,
widget=widget.HiddenWidget(),
)
def form_validator(form, value):
# value.update(value['secondari'])
# value.update(value['primari'])
def err_captcha():
msg = 'Captcha harus diisi'
raise colander.Invalid(form, msg)
def err_email():
raise colander.Invalid(
form, 'e-mail %s sudah ada yang menggunakan' % value['email'])
def err_nik(kode):
raise colander.Invalid(
form, 'NIK %s sudah ada yang menggunakan' % kode)
def err_login():
raise colander.Invalid(
form, 'User atau Password tidak sesuai')
def err_mobile():
raise colander.Invalid(
form, 'Nomor %s sudah ada yang menggunakan' % value['mobile'])
request = form.request
# Cek Login
if 'password' in value:
user = form.request.user
if not user or not UserService.check_password(user, value['password']):
err_login()
if not request.user:
if 'captcha' not in value or not value['captcha'] \
or 'captcha' not in request.session or not request.session['captcha']:
err_captcha()
captcha = 'captcha' in value and value['captcha'].upper() or None
if not captcha or captcha != request.session['captcha']:
err_captcha()
if 'id' in request.matchdict:
uid = request.matchdict['id']
q = DBSession.query(Partner).filter_by(id=uid)
partner = q.first()
else:
partner = None
# CEK NIK apakah Sudah Ada di tabel Partner?
primari = value['primari']
kode = 'kode' in primari and primari['kode'] or ""
if not kode:
kode = primari["email"]
found_nik = nik_found(primari['kode'])
if partner:
if found_nik and found_nik.id != partner.id:
err_nik(kode)
elif found_nik:
err_nik(kode)
if 'mobile' in value and value['mobile']:
mobile = value['mobile']
found = mobile_found_partner(mobile).first()
if partner:
if found and found.id != partner.id:
err_mobile()
elif found:
err_mobile()
# user = email_found_user(email)
# # jika ada user dan statusnya register di buat error
# if user and not form.request.user:
# err_email()
#
# # jika update periksa apakah email digunakan oleh user lain
# if user and form.request.user:
# if user.id != form.request.user.id:
# err_email()
def get_form(request, class_form, buttons=None, validator=form_validator):
schema = class_form(validator=validator)
schema = schema.bind()
schema.request = request
if buttons:
return Form(schema, buttons=buttons)
return Form(schema, buttons=('batal', 'simpan'))
def save(values, user=None, row=None, request=None):
"""
Digunakan untuk menyimpan User External
:param values: dictionary of
external_id
external_user_name
provider_name
access_token
alt_token
token_secret
:param user: object user if none create new user
:param row: object external_identify if none create new
:return: user objek
"""
if not user:
user_ = dict(user_name=values['external_user_name'],
email=values['external_email'])
user, remail = save_user(request, user_)
if not row:
row = ExternalIdentity()
row.from_dict(values)
# try:
# except:
# transaction.rollback()
row.local_user_id = user.id
DBSession.add(row)
DBSession.flush()
return user
def save_request(values, request, row=None):
if 'id' in request.matchdict:
values['id'] = request.matchdict['id']
id_info = request.session['id_info']
user = ExternalIdentityService.user_by_external_id_and_provider(
id_info['sub'], id_info['iss'])
if not user:
user = save(values, user, row, request)
partner = Partner.query_email(id_info['email']).first()
# if not partner:
values['email'] = id_info['email']
if 'kode' not in values and not values['kode']:
values['kode'] = id_info['email']
values['user_id'] = user.id
save_partner(values, partner)
##Untuk SIMKEL##
settings = get_settings()
if 'default_group'in settings:
groups = settings['default_group'].split(',')
for group in groups:
group_data = Group.query_group_name(group).first()
if not group_data:
raise custom_error(-1,"Group Not Found.")
data=dict(group_id= group_data.id,
user_id= user.id)
save_groups(data,None)
return user
def route_list(request):
return HTTPFound(location=request.route_url('home'))
def reg_buttons():
btn_register = Button(name='register', css_class='btn-success', type="submit")
btn_cancel = Button(name='batal', css_class='btn-primary', type="submit")
return btn_cancel, btn_register
class RegistrasiExternal(BaseView):
@view_config(route_name='register-external', renderer='templates/register.pt')
def view_add(self):
request = self.req
if 'id_info' not in request.session:
return HTTPFound(location=request.route_url("login"))
if request.user:
partner = Partner.query_email(request.user.email).first()
if partner:
return HTTPFound(location=request.route_url("profile-external",
id=partner.id))
id_info = request.session['id_info']
form = get_form(request, RegSchema, reg_buttons())
if request.POST:
if 'register' in request.POST:
controls = request.POST.items()
try:
controls = form.validate(controls)
except ValidationFailure as e:
values = e.cstruct
values['primari']['email'] = id_info['email']
# values['detail']['captcha']
form.set_appstruct(values)
return dict(form=form, captcha=get_captcha(request), scripts="")
dicts = dict(controls)
values = dicts['primari']
values.update(dicts['secondari'])
values['mobile'] = dicts['mobile']
values['email'] = id_info['email']
values['external_id'] = id_info['sub']
values['external_user_name'] = id_info["name"]
values['external_email'] = id_info["email"]
values['provider_name'] = id_info["iss"]
# todo: what is this????
# values['access_token']
# values['alt_token']
# values['token_secret']
user = save_request(values, request)
headers = get_login_headers(request, user)
request.session.flash('Registrasi Sukses.')
if 'captcha' in request.session:
del(request.session['captcha'])
return HTTPFound(location=request.route_url('home'), headers=headers)
values = dict()
values['primari'] = dict(
email=id_info['email'])
values['secondari'] = dict(
nama=id_info['name'])
if request.user:
partner = Partner.query_user_id(request.user.id).first()
if partner:
values['primari'].update(partner.to_dict())
values['secondari'].update(partner.to_dict())
form.set_appstruct(values)
# return dict()
# return dict(captcha=get_captcha(request))
return dict(form=form.render(), captcha=get_captcha(request), scripts="")
@view_config(route_name='profile-external', renderer='templates/register.pt',
permission='view')
def profile_external(self):
request = self.req
query = query_id(request)
row = query.first()
if not row:
return HTTPFound(location=request.route_url("register-external"))
form = get_form(request, RegEditSchema)
if request.POST:
if 'simpan' in request.POST:
controls = request.POST.items()
try:
controls = form.validate(controls)
except ValidationFailure as e:
values = e.cstruct
form.set_appstruct(values)
return dict(form=form)
values = dict(controls)
save_request(values['secondari'], request, row)
request.session.flash('Sukses Update Profile.')
return route_list(request)
values = row.to_dict()
email = row.email
emails = email.split('@')
result = emails[0][:3]
for a in range(3, len(emails[0])):
result = "".join([result, "*"])
n = emails[1].find(".")
provider = emails[1][:n]
ext = emails[1][n:]
result = "".join([result, '@', provider[:3]])
for a in range(3, len(provider)):
result = "".join([result, "*"])
result = "".join([result, ext])
mobile = row.mobile
result2 = "".join([mobile[:4], "****", mobile[8:]])
# values['email'] = result
values['secondari'] = row.to_dict()
values['primari'] = row.to_dict()
values['primari']["email"] = result
values["mobile"] = result2
form.set_appstruct(values)
return dict(form=form, captcha=None)
########
# Edit #
########
def query_id(request):
return DBSession.query(Partner).\
join(User, Partner.user_id == User.id).\
filter(User.id == request.user.id)
def id_not_found(request):
msg = 'Register ID %s Tidak Ditemukan.' % request.matchdict['id']
request.session.flash(msg, 'error')
return route_list(request)
# # Module ini digunakan untuk registrasi user external
# # Restriction dari module ini tidak boleh diubah emailnya
# from email.utils import parseaddr
# import colander
# from deform import (Form, widget, ValidationFailure, Button)
# from opensipkd.tools.api import custom_error
# from opensipkd.base.views.user_login import get_login_headers
# from opensipkd.base.views.user import insert as save_user
# from pyramid.httpexceptions import HTTPFound
# from pyramid.i18n import TranslationStringFactory
# from pyramid.view import view_config
# from ziggurat_foundations.models.services.user import UserService
#
# # from . import get_login_headers
# # from .register import mobile_found_partner, save_partner, nik_found
# from .user_group import save as save_groups
# from ..models import DBSession, Partner, Group, ExternalIdentity, User, ExternalIdentityService
# from opensipkd.tools import get_settings
# from opensipkd.tools.captcha import get_captcha
# from ..views import BaseView
#
# # from .user import email_validator
# _ = TranslationStringFactory('user')
#
#
# def email_validator(node, value):
# name, email = parseaddr(value)
# if not email or email.find('@') < 0:
# raise colander.Invalid(node, 'Invalid email format')
#
#
# class PrimarySchema(colander.Schema):
# kode = colander.SchemaNode(
# colander.String(),
# widget=widget.TextInputWidget(),
# oid="kode",
# title="NIK"
# )
#
# email = colander.SchemaNode(
# colander.String(),
# widget=widget.TextInputWidget(readonly=True),
# missing=colander.drop,
# title="E-mail",
# validator=email_validator,
# oid="email")
#
#
# class SecondarySchema(colander.Schema):
# nama = colander.SchemaNode(
# colander.String(),
# oid="nama")
# alamat_1 = colander.SchemaNode(
# colander.String(),
# title="Alamat",
# oid="alamat_1")
# alamat_2 = colander.SchemaNode(
# colander.String(),
# title="",
# missing=colander.drop,
# oid="alamat_2")
#
#
# class RegSchema(colander.Schema):
# primari = PrimarySchema()
# mobile = colander.SchemaNode(
# colander.String(),
# widget=widget.TextInputWidget(),
# oid="mobile")
# secondari = SecondarySchema()
# captcha = colander.SchemaNode(
# colander.String(),
# oid="captcha")
#
#
# class RegEditSchema(colander.Schema):
# primari = PrimarySchema()
# mobile = colander.SchemaNode(
# colander.String(),
# widget=widget.TextInputWidget(readonly=True),
# missing=colander.drop,
# oid="mobile")
# secondari = SecondarySchema()
# id = colander.SchemaNode(
# colander.Integer(),
# missing=colander.drop,
# widget=widget.HiddenWidget(),
# )
#
#
# def form_validator(form, value):
# # value.update(value['secondari'])
# # value.update(value['primari'])
#
# def err_captcha():
# msg = 'Captcha harus diisi'
# raise colander.Invalid(form, msg)
#
# def err_email():
# raise colander.Invalid(
# form, 'e-mail %s sudah ada yang menggunakan' % value['email'])
#
# def err_nik(kode):
# raise colander.Invalid(
# form, 'NIK %s sudah ada yang menggunakan' % kode)
#
# def err_login():
# raise colander.Invalid(
# form, 'User atau Password tidak sesuai')
#
# def err_mobile():
# raise colander.Invalid(
# form, 'Nomor %s sudah ada yang menggunakan' % value['mobile'])
#
# request = form.request
# # Cek Login
# if 'password' in value:
# user = form.request.user
# if not user or not UserService.check_password(user, value['password']):
# err_login()
#
# if not request.user:
# if 'captcha' not in value or not value['captcha'] \
# or 'captcha' not in request.session or not request.session['captcha']:
# err_captcha()
#
# captcha = 'captcha' in value and value['captcha'].upper() or None
#
# if not captcha or captcha != request.session['captcha']:
# err_captcha()
#
# if 'id' in request.matchdict:
# uid = request.matchdict['id']
# q = DBSession.query(Partner).filter_by(id=uid)
# partner = q.first()
# else:
# partner = None
#
# # CEK NIK apakah Sudah Ada di tabel Partner?
#
# primari = value['primari']
# kode = 'kode' in primari and primari['kode'] or ""
# if not kode:
# kode = primari["email"]
#
# found_nik = nik_found(primari['kode'])
# if partner:
# if found_nik and found_nik.id != partner.id:
# err_nik(kode)
# elif found_nik:
# err_nik(kode)
#
# if 'mobile' in value and value['mobile']:
# mobile = value['mobile']
#
# found = mobile_found_partner(mobile).first()
# if partner:
# if found and found.id != partner.id:
# err_mobile()
# elif found:
# err_mobile()
#
# # user = email_found_user(email)
# # # jika ada user dan statusnya register di buat error
# # if user and not form.request.user:
# # err_email()
# #
# # # jika update periksa apakah email digunakan oleh user lain
# # if user and form.request.user:
# # if user.id != form.request.user.id:
# # err_email()
#
#
# def get_form(request, class_form, buttons=None, validator=form_validator):
# schema = class_form(validator=validator)
# schema = schema.bind()
# schema.request = request
# if buttons:
# return Form(schema, buttons=buttons)
# return Form(schema, buttons=('batal', 'simpan'))
#
#
# def save(values, user=None, row=None, request=None):
# """
# Digunakan untuk menyimpan User External
# :param values: dictionary of
# external_id
# external_user_name
# provider_name
# access_token
# alt_token
# token_secret
#
# :param user: object user if none create new user
# :param row: object external_identify if none create new
# :return: user objek
# """
# if not user:
# user_ = dict(user_name=values['external_user_name'],
# email=values['external_email'])
# user, remail = save_user(request, user_)
#
# if not row:
# row = ExternalIdentity()
#
# row.from_dict(values)
# # try:
# # except:
# # transaction.rollback()
#
# row.local_user_id = user.id
# DBSession.add(row)
# DBSession.flush()
# return user
#
#
# def save_request(values, request, row=None):
# if 'id' in request.matchdict:
# values['id'] = request.matchdict['id']
#
# id_info = request.session['id_info']
# user = ExternalIdentityService.user_by_external_id_and_provider(
# id_info['sub'], id_info['iss'])
# if not user:
# user = save(values, user, row, request)
#
# partner = Partner.query_email(id_info['email']).first()
# # if not partner:
# values['email'] = id_info['email']
# if 'kode' not in values and not values['kode']:
# values['kode'] = id_info['email']
# values['user_id'] = user.id
# save_partner(values, partner)
# ##Untuk SIMKEL##
# settings = get_settings()
# if 'default_group'in settings:
# groups = settings['default_group'].split(',')
# for group in groups:
# group_data = Group.query_group_name(group).first()
# if not group_data:
# raise custom_error(-1,"Group Not Found.")
# data=dict(group_id= group_data.id,
# user_id= user.id)
# save_groups(data,None)
# return user
#
#
# def route_list(request):
# return HTTPFound(location=request.route_url('home'))
#
#
# def reg_buttons():
# btn_register = Button(name='register', css_class='btn-success', type="submit")
# btn_cancel = Button(name='batal', css_class='btn-primary', type="submit")
# return btn_cancel, btn_register
#
#
# class RegistrasiExternal(BaseView):
# @view_config(route_name='register-external', renderer='templates/register.pt')
# def view_add(self):
# request = self.req
# if 'id_info' not in request.session:
# return HTTPFound(location=request.route_url("login"))
#
# if request.user:
# partner = Partner.query_email(request.user.email).first()
# if partner:
# return HTTPFound(location=request.route_url("profile-external",
# id=partner.id))
#
# id_info = request.session['id_info']
# form = get_form(request, RegSchema, reg_buttons())
# if request.POST:
# if 'register' in request.POST:
# controls = request.POST.items()
# try:
# controls = form.validate(controls)
# except ValidationFailure as e:
# values = e.cstruct
# values['primari']['email'] = id_info['email']
# # values['detail']['captcha']
# form.set_appstruct(values)
# return dict(form=form, captcha=get_captcha(request), scripts="")
#
# dicts = dict(controls)
# values = dicts['primari']
# values.update(dicts['secondari'])
# values['mobile'] = dicts['mobile']
# values['email'] = id_info['email']
# values['external_id'] = id_info['sub']
# values['external_user_name'] = id_info["name"]
# values['external_email'] = id_info["email"]
# values['provider_name'] = id_info["iss"]
# # todo: what is this????
# # values['access_token']
# # values['alt_token']
# # values['token_secret']
# user = save_request(values, request)
#
# headers = get_login_headers(request, user)
# request.session.flash('Registrasi Sukses.')
# if 'captcha' in request.session:
# del(request.session['captcha'])
# return HTTPFound(location=request.route_url('home'), headers=headers)
#
# values = dict()
# values['primari'] = dict(
# email=id_info['email'])
#
# values['secondari'] = dict(
# nama=id_info['name'])
#
# if request.user:
# partner = Partner.query_user_id(request.user.id).first()
# if partner:
# values['primari'].update(partner.to_dict())
# values['secondari'].update(partner.to_dict())
#
# form.set_appstruct(values)
# # return dict()
# # return dict(captcha=get_captcha(request))
# return dict(form=form.render(), captcha=get_captcha(request), scripts="")
#
# @view_config(route_name='profile-external', renderer='templates/register.pt',
# permission='view')
# def profile_external(self):
# request = self.req
# query = query_id(request)
# row = query.first()
# if not row:
# return HTTPFound(location=request.route_url("register-external"))
#
# form = get_form(request, RegEditSchema)
# if request.POST:
# if 'simpan' in request.POST:
# controls = request.POST.items()
# try:
# controls = form.validate(controls)
# except ValidationFailure as e:
# values = e.cstruct
# form.set_appstruct(values)
# return dict(form=form)
# values = dict(controls)
# save_request(values['secondari'], request, row)
# request.session.flash('Sukses Update Profile.')
#
# return route_list(request)
#
# values = row.to_dict()
# email = row.email
# emails = email.split('@')
# result = emails[0][:3]
# for a in range(3, len(emails[0])):
# result = "".join([result, "*"])
#
# n = emails[1].find(".")
# provider = emails[1][:n]
# ext = emails[1][n:]
# result = "".join([result, '@', provider[:3]])
#
# for a in range(3, len(provider)):
# result = "".join([result, "*"])
#
# result = "".join([result, ext])
# mobile = row.mobile
# result2 = "".join([mobile[:4], "****", mobile[8:]])
# # values['email'] = result
# values['secondari'] = row.to_dict()
# values['primari'] = row.to_dict()
# values['primari']["email"] = result
# values["mobile"] = result2
#
# form.set_appstruct(values)
# return dict(form=form, captcha=None)
#
#
# ########
# # Edit #
# ########
# def query_id(request):
# return DBSession.query(Partner).\
# join(User, Partner.user_id == User.id).\
# filter(User.id == request.user.id)
#
#
# def id_not_found(request):
# msg = 'Register ID %s Tidak Ditemukan.' % request.matchdict['id']
# request.session.flash(msg, 'error')
# return route_list(request)
<html metal:use-macro="load: ./base3.1.pt">
<js metal:fill-slot="js_files">
<script src="${home}/static/v3/js/plugin/datatables/jquery.dataTables.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.colVis.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.tableTools.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.bootstrap.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatable-responsive/datatables.responsive.min.js"></script>
</js>
</html>
......@@ -3,6 +3,7 @@
tal:define="
home request.route_url('home')[:-1];
user_path ['user', 'user-add', 'user-edit', 'user-view', 'user-delete'];
user_ext_path ['user-ext', 'user-ext-view', 'user-ext-delete'];
group_path ['group', 'group-add', 'group-edit', 'group-view', 'group-delete'];
param_path ['parameter', 'parameter-add', 'parameter-edit', 'parameter-view', 'parameter-delete'];
dep_path ['departemen', 'departemen-add', 'departemen-edit', 'departemen-view', 'departemen-delete'];
......@@ -15,6 +16,8 @@
dati2_path ['dati2', 'dati2-add', 'dati2-edit', 'dati2-view', 'dati2-delete'];
kecamatan_path ['kecamatan', 'kecamatan-add', 'kecamatan-edit', 'kecamatan-view', 'kecamatan-delete'];
desa_path ['desa', 'desa-add', 'desa-edit', 'desa-view', 'desa-delete'];
css css|[];
js js|[];
">
<head>
......@@ -26,6 +29,10 @@
<meta name="author" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- FAVICONS -->
<link rel="shortcut icon" href="${home}/static/v3/img/favicon.png" type="image/x-icon">
<link rel="icon" href="${home}/static/v3/img/favicon.png" type="image/x-icon">
<!-- GOOGLE FONT -->
<link rel="stylesheet" href="${home}/static/v3/css/gf_open_sans-400italic_700italic_300_400_700.css">
......@@ -43,45 +50,18 @@
<!-- We recommend you use "your_style.css" to override SmartAdmin
specific styles this will also ensure you retrain your customization with each SmartAdmin update. -->
<link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/osipkd.css">
<!-- FAVICONS -->
<link rel="shortcut icon" href="${home}/static/v3/img/favicon.png" type="image/x-icon">
<link rel="icon" href="${home}/static/v3/img/favicon.png" type="image/x-icon">
<!-- OTHER CSS -->
<link href="${home}/static/v3/js/plugin/bootstrap-datepicker/css/bootstrap-datepicker.min.css"
rel="stylesheet">
<tal:loop tal:repeat="css_resource css">
<link rel="stylesheet" href="${home}${request.static_path(css_resource)}"
type="text/css">
</tal:loop>
<!--? <link href="${home}/static/v3/js/plugin/bootstrap-datepicker/css/bootstrap-datepicker.min.css"-->
<!--? rel="stylesheet">-->
<link href="${home}/deform_static/css/form.css" rel="stylesheet">
<link href="${home}/deform_static/css/typeahead.css" rel="stylesheet">
<link href="${home}/static/v3/css/select2.min.css" rel="stylesheet" type="text/css">
<link href="${home}/static/css/custom.css" rel="stylesheet" type="text/css">
<!--? <link href="${home}/static/v3/css/select2.min.css" rel="stylesheet" type="text/css">-->
<metal:css define-slot="css_files"></metal:css>
<style metal:define-slot="style">
.twitter-typeahead {
font-size: 12px !important;
margin-bottom: 0;
width: 100%;
height: 26px;
position: absolute;
top: 0;
left: 0;
z-index: auto;
}
.twitter-typeahead .tt-query, .twitter-typeahead .tt-hint {
font-size: 12px !important;
margin-bottom: 0;
width: 100%;
height: 26px;
position: absolute;
top: 0;
left: 0;
z-index: auto;
}
</style>
<link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/osipkd.css">
</head>
<body class="fixed-header">
......@@ -92,14 +72,11 @@
<!-- #HEADER -->
<header id="header">
<div id="logo-group">
<!-- PLACE YOUR LOGO HERE -->
<h3 id="logo">
<a href="${home}/"><img src="${home}/static/img/logo.png" alt=""></a>
<a href="${home}/"><img src="${home}/static/img/logo.png" alt="LOGO"></a>
</h3>
<!-- END LOGO PLACEHOLDER -->
</div>
<!-- #PROJECTS: projects dropdown -->
......@@ -113,7 +90,6 @@
<div class="pull-right">
<div tal:condition="request.user" class="project-context hidden-xs">
<span class="label"><i class="fa fa-sm fa-fw fa-institution"></i> ${request.company}</span>
<span tal:condition="request.user" class="project-selector dropdown-toggle" data-toggle="dropdown">Pilih Module <i
class="fa fa-angle-down"></i></span>
<ul tal:condition="request.user" class="dropdown-menu">
......@@ -121,7 +97,6 @@
<a href="${home}/${menu}">${request.menus[menu]}</a>
</li>
</ul>
</div>
<!-- collapse menu button -->
<div id="hide-menu" class="btn-header pull-right">
......@@ -132,8 +107,8 @@
<!-- fullscreen button -->
<div id="fullscreen" class="btn-header transparent pull-right">
<span> <a href="javascript:void(0);" data-action="launchFullscreen" title="Full Screen"><i
class="fa fa-arrows-alt"></i></a> </span>
<span> <a href="javascript:void(0);" data-action="launchFullscreen" title="Full Screen">
<i class="fa fa-arrows-alt"></i></a> </span>
</div>
<!-- end fullscreen button -->
......@@ -142,8 +117,7 @@
<li>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-lg fa-fw fa-user"></i> <span
style="text-transform:capitalize"> ${request.user and request.user.nice_username() or ""} </span>
<i
class="fa fa-angle-down"></i> </a>
<i class="fa fa-angle-down"></i> </a>
<ul class="dropdown-menu pull-right">
<li><a style="text-transform:capitalize" href="${request.route_url('profile')}">Profile</a></li>
<li tal:condition="not request.user.external">
......@@ -161,10 +135,8 @@
</li>
</ul>
<!-- end user info -->
</div>
<!-- end pulled right: nav area -->
</header>
<!-- END HEADER -->
......@@ -172,32 +144,27 @@
<!-- Left panel : Navigation area -->
<!-- Note: This width of the aside area can be adjusted through LESS variables -->
<aside id="left-panel" style="padding-bottom:67px">
<!-- NAVIGATION : This navigation is also responsive-->
<nav style="">
<!-- Modul Menu -->
<ul metal:define-slot="navs"></ul>
<!-- Admin Menu -->
<ul
tal:condition="has_permission(request, user_path)"
style="margin-top: 0; padding-top: 0;">
<ul tal:condition="has_permission(request, user_path)" style="margin-top: 0; padding-top: 0;">
<li>
<a href="#"><i class="fa fa-lg fa-fw fa-shield"></i>
<span class="menu-item-parent">Admin</span></a>
<a href="#"><i class="fa fa-lg fa-fw fa-shield"></i><span class="menu-item-parent">Admin</span></a>
<ul>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"
tal:attributes="class request.matched_route.name in user_path and 'active'">
<a href="${home}/user">User</a>
</li>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"
tal:attributes="class request.matched_route.name in user_ext_path and 'active'">
<a href="${home}/user/ext">External User</a>
</li>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"
tal:attributes="class request.matched_route.name in group_path and 'active'">
<a href="${home}/group">Group</a>
</li>
<!-- <li tal:condition="has_permission(request, 'user-group')"-->
<!-- tal:attributes="class request.matched_route.name in ['user-group'] and 'active'">-->
<!-- <a href="${home}/user/group">User Group</a></li>-->
<li tal:condition="has_permission(request, 'upload-logo')"
tal:attributes="class request.matched_route.name in ['upload-logo'] and 'active'">
<a href="${home}/upload/logo">Upload Logo</a></li>
......@@ -217,10 +184,6 @@
<li tal:condition="has_permission(request, 'departemen')"
tal:attributes="class request.matched_route.name in dep_path and 'active'">
<a href="${home}/departemen">Departemen</a></li>
<!-- <li tal:condition="has_permission(request, 'departemen-user')"-->
<!-- tal:attributes="class request.matched_route.name in ['departemen-user'] and 'active'">-->
<!-- <a href="${home}/departemen/user">User Departemen</a></li>-->
<li tal:condition="has_permission(request, 'partner')"
tal:attributes="class request.matched_route.name in partner_path and 'active'">
<a href="${home}/partner">Partner</a></li>
......@@ -233,7 +196,6 @@
<li tal:condition="has_permission(request, 'dati2')"
tal:attributes="class request.matched_route.name in dati2_path and 'active'">
<a href="${home}/dati2">Kabupaten/Kota</a></li>
<li tal:condition="has_permission(request, 'kecamatan')"
tal:attributes="class request.matched_route.name in kecamatan_path and 'active'">
<a href="${home}/kecamatan">Kecamatan</a></li>
......@@ -246,7 +208,6 @@
</ul>
</li>
</ul>
</nav>
<span class="minifyme" data-action="minifyMenu">
<i class="fa fa-arrow-circle-left hit"></i>
......@@ -265,14 +226,11 @@
document.write('<script src="${home}/static/v3/js/libs/jquery-2.1.1.min.js"><\/script>');
}
</script>
<script src="${home}/static/v3/js/jquery-ui-1.10.3.min.js"></script>
<!--?<script src="${home}/static/v3/js/jquery-ui-1.10.3.min.js"></script>-->
<script>
if (!window.jQuery.ui) {
document.write('<script src="${home}/static/v3/js/libs/jquery-ui-1.10.3.min.js"><\/script>');
}
// if (!window.jQuery.ui) {
<!--? document.write('<script src="${home}/static/v3/js/libs/jquery-ui-1.10.3.min.js"><\/script>');-->
// }
</script>
<!-- IMPORTANT: APP CONFIG -->
......@@ -294,83 +252,27 @@
<script src="${home}/static/v3/js/app.min.js"></script>
<!-- PAGE RELATED PLUGIN(S) -->
<script src="${home}/static/v3/js/plugin/datatables/jquery.dataTables.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.colVis.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.tableTools.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatables/dataTables.bootstrap.min.js"></script>
<script src="${home}/static/v3/js/plugin/datatable-responsive/datatables.responsive.min.js"></script>
<script src="${home}/static/v3/js/plugin/bootstrap-datepicker/js/bootstrap-datepicker.min.js"></script>
<script src="${home}/static/v3/js/plugin/bootstrap-timepicker/bootstrap-timepicker.min.js"></script>
<script src="${home}/deform_static/scripts/deform.js"></script>
<script src="${home}/deform_static/scripts/typeahead.min.js"></script>
<script src="${home}/deform_static/scripts/jquery.maskMoney-3.1.1.min.js"></script>
<script src="${home}/deform_static/tinymce/tinymce.min.js"></script>
<script src="${home}/static/v3/js/tools.js"></script>
<script src="${home}/static/v3/js/notification/SmartNotification.min.js"></script>
<script src="${home}/static/v3/js/plugin/masked-input/jquery.maskedinput.min.js"></script>
<script src="${home}/static/v3/js/select2.full.min.js"></script>
<script src="${home}/deform_static/scripts/file_upload.js"></script>
<script>
function showError(msg) {
$("#success").css('display', 'none', 'important');
$("#errors").css('display', 'box', 'important');
$("#errors").html("<span class='glyphicon glyphicon-remove'></span> " + msg);
console.log(msg);
};
function showSuccess(msg) {
$("#errors").css('display', 'none', 'important');
$("#success").css('display', 'box', 'important');
$("#success").html("<span class='glyphicon glyphicon-ok'></span> " + msg);
};
$(function () {
var current = location.pathname;
$('nav li a').each(function () {
var $this = $(this);
if ($this.attr('href') != '' && $this.attr('href') != '#') {
if ($this.attr('href') == current) {
$this.parent().addClass('active');
var ul_parent = $this.parents('ul');
ul_parent.show();
ul_parent.parents('li').addClass('open');
}
}
})
});
$(document).ready(function () {
// DO NOT REMOVE : GLOBAL FUNCTIONS!
pageSetUp();
/*
* PAGE RELATED SCRIPTS
*/
});
function number_format(number, decimals, dec_point, thousands_sep) {
// Strip all characters but numerical ones.
number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
var n = !isFinite(+number) ? 0 : +number,
prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
s = '',
toFixedFix = function (n, prec) {
var k = Math.pow(10, prec);
return '' + Math.round(n * k) / k;
};
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
</script>
<!--?<script src="${home}/static/v3/js/plugin/datatables/jquery.dataTables.min.js"></script>-->
<!--?<script src="${home}/static/v3/js/plugin/datatables/dataTables.colVis.min.js"></script>-->
<!--?<script src="${home}/static/v3/js/plugin/datatables/dataTables.tableTools.min.js"></script>-->
<!--?<script src="${home}/static/v3/js/plugin/datatables/dataTables.bootstrap.min.js"></script>-->
<!--?<script src="${home}/static/v3/js/plugin/datatable-responsive/datatables.responsive.min.js"></script>-->
<!--?<script src="${home}/static/v3/js/plugin/bootstrap-datepicker/js/bootstrap-datepicker.min.js"></script>-->
<!--?<script src="${home}/static/v3/js/plugin/bootstrap-timepicker/bootstrap-timepicker.min.js"></script>-->
<!--?<script src="${home}/deform_static/scripts/deform.js"></script>-->
<!--?<script src="${home}/deform_static/scripts/typeahead.min.js"></script>-->
<!--?<script src="${home}/deform_static/scripts/jquery.maskMoney-3.1.1.min.js"></script>-->
<!--?<script src="${home}/deform_static/tinymce/tinymce.min.js"></script>-->
<!--?<script src="${home}/static/v3/js/tools.js"></script>-->
<!--?<script src="${home}/static/v3/js/notification/SmartNotification.min.js"></script>-->
<!--?<script src="${home}/static/v3/js/plugin/masked-input/jquery.maskedinput.min.js"></script>-->
<!--?<script src="${home}/static/v3/js/select2.full.min.js"></script>-->
<!--?<script src="${home}/deform_static/scripts/file_upload.js"></script>-->
<script src="${home}/static/v3/js/osipkd.js"></script>
<tal:loop tal:repeat="js_resource js">
<script src="${home}${request.static_path(js_resource)}"></script>
</tal:loop>
<metal:js define-slot="js_files"></metal:js>
......
<html metal:use-macro="load: ./base3.1.pt">
<html metal:use-macro="load: ./_table.pt">
<span metal:fill-slot="scripts">
<script>
var btn_view='<button id="btn_view" class="btn btn btn-general" type="button">'+
......
<html metal:use-macro="load: ../base3.1.pt">
<html metal:use-macro="load: ../_table.pt">
<link metal:fill-slot="css_files" rel="stylesheet" type="text/css" media="screen" href="/static/v3/css/custom-datatable.css">
<div metal:fill-slot="content">
<div class="jarviswidget" style="border-top:1px solid #ccc!important">
......
<html metal:use-macro="load: ./base3.1.pt">
<div metal:fill-slot="content">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-fw fa-plus"></i>&nbsp;${request.title}</h3>
</div>
<div class="panel-body">
<div tal:content="structure form"></div>
</div>
</div>
</div>
<div metal:fill-slot="scripts">
<script>
// $(document).ready(function () {
// $(".read-only").attr("readonly", true);
// $(".readonly").attr("readonly", true);
// $(".date").attr("readonly", true);
// $(".date").datepicker({
// format: 'dd-mm-yyyy'
// });
<!--? ${structure:scripts}-->
// });
</script>
<div metal:define-slot="scripts"></div>
</div>
</html>
<div metal:use-macro="load: ../main.pt">
<div metal:fill-slot="content">
<div class="well">
<div tal:content="structure form"/>
</div>
</div>
</div>
<div metal:use-macro="load: ../main.pt">
<div metal:fill-slot="content">
<div class="well">
<div tal:content="structure form"/>
</div>
</div>
</div>
<div metal:use-macro="load: ../main.pt">
<div metal:fill-slot="content">
<div class="jarviswidget" style="border-top:1px solid #ccc!important">
<div role="content">
<table id="table1" class="table table-bordered table-hover table-condensed">
<thead>
<tr>
<th>ID</th>
<th>Nama Group</th>
<th>Deskripsi</th>
<th>Jml. Anggota</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
<script type="text/javascript" metal:fill-slot="scripts">
var mID;
var oTable;
var oTableUri = "${home}/group"
var oTableUrl = oTableUri + "/grid/act";
$(document).ready(function () {
oTable = $('#table1').DataTable({
dom: '<"row"<"col-md-8"<"toolbar">l><"col-md-4"f>>rtip',
processing: true,
serverSide: true,
ajax: oTableUrl,
stateSave: true,
scrollCollapse: true,
sort: true,
info: false,
filter: true,
autoWidth: false,
paginate: true,
paginationType: "full_numbers",
lengthMenu: [
[10, 25, 50, 100],
[10, 25, 50, 100]
],
columnDefs: [{
searchable: false,
visible: false,
targets: [0]
}],
columns: [{
"data": "id"
},
{
"data": "name",
"width": "200px",
"class": "left"
},
{
"data": "desc"
},
{
"data": "member",
"width": "200px",
"class": "center"
},
],
"language": {
"search": "Cari: ",
"paginate": {
"first": "Pertama ",
"last": "Akhir ",
"previous": "",
"next": "",
},
"lengthMenu": "Tampil _MENU_ baris "
},
});
var tb_array = [
'<div class="btn-group pull-left"> ',
' <button id="btn_view" class="btn btn btn-warning" type="button" data-toggle="tooltip" title="View"> ' +
' <i class="fa fa-eye"></i></button>',
' <button id="btn_add" class="btn btn btn-success" type="button" data-toggle="tooltip" title="Tambah">' +
' <i class="fa fa-plus"></i></button>',
' <button id="btn_edit" class="btn btn btn-warning" type="button" data-toggle="tooltip" title="Ubah">' +
' <i class="fa fa-edit"></i></button>',
' <button id="btn_delete" class="btn btn btn-danger" type="button" data-toggle="tooltip" title="Hapus">' +
' <i class="fa fa-trash-o"></i></button>',
' <button id="btn_pdf" class="btn btn btn-primary" type="button" data-toggle="tooltip" title="PDF">' +
' <i class="fa fa-file-pdf-o"></i></button>',
' <button id="btn_csv" class="btn btn btn-primary" type="button" data-toggle="tooltip" title="CSV">' +
' <i class="fa fa-file-excel-o"></i></button>',
' <button id="btn_close" class="btn btn btn-warning" type="button" data-toggle="tooltip" title="Tutup">' +
' <i class="fa fa-arrow-right"></i></button>',
' &nbsp;',
'</div>',
];
var tb = tb_array.join(' ');
$("div.toolbar").html(tb);
$("div.toolbar").attr('style', 'display:block; float: left; margin-bottom:6px; line-height:16px;');
$('#table1 tbody').on('click', 'tr', function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
} else {
var aData = oTable.row(this).data();
oTable.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
mID = aData.id;
console.log(mID);
oTable.$('tr.row_selected').removeClass('row_selected');
$(this).addClass('row_selected');
/*oTable2.fnReloadAjax("egaji/grid2?id=" + mID);*/
}
});
$('#btn_add').click(function () {
window.location = oTableUri + '/add';
});
$('#btn_edit').click(function () {
if (mID) window.location = oTableUri + '/' + mID + '/edit';
else
$.SmartMessageBox({
title: "Edit",
content: "Pilih Baris yang akan di edit...",
buttons: '[Oke]'
});
;
});
$('#btn_view').click(function () {
if (mID) window.location = oTableUri + '/' + mID + '/view';
else
$.SmartMessageBox({
title: "View",
content: "Pilih Baris yang akan di lihat...",
buttons: '[Ok]'
});
;
});
$('#btn_delete').click(function () {
if (mID) window.location = oTableUri + '/' + mID + '/delete';
else
$.SmartMessageBox({
title: "Hapus",
content: "Pilih Baris yang akan di hapus...",
buttons: '[Oke]'
});
});
$('#btn_csv').click(function () {
url = oTableUri + "/csv/rpt";
window.open(url);
});
$('#btn_pdf').click(function () {
url = oTableUri + "/pdf/rpt";
window.open(url);
});
$("#btn_close").click(function () {
window.location = '/';
return false;
});
});
</script>
</div>
<html metal:use-macro="load: ../base3.1.pt">
<html metal:use-macro="load: ../_table.pt">
<link metal:fill-slot="css_files" rel="stylesheet" type="text/css" media="screen"
href="/static/v3/css/custom-datatable.css">
<div metal:fill-slot="content">
......
<html metal:use-macro="load: ../main.pt">
<html metal:use-macro="load: ../_table.pt">
<!-- content -->
<div metal:fill-slot="content">
......
<html metal:use-macro="load: ../main.pt">
<html metal:use-macro="load: ../_table.pt">
<div metal:fill-slot="content">
<div class="jarviswidget" style="border-top:1px solid #ccc!important">
......
<html metal:use-macro="load: ../main.pt">
<!-- content -->
<div metal:fill-slot="content">
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">Hapus data</h3>
</div>
<div class="panel-body">
Hapus Group #${row.group_name} ${row.description} ?
</div>
<html metal:use-macro="load: ./_table.pt">
<div metal:fill-slot="content">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-fw fa-plus"></i>&nbsp;${request.title}</h3>
</div>
<div class="panel-body">
<div tal:content="structure form"></div>
</div>
<div tal:content="structure form"/>
</div>
<!-- end content -->
</div>
</html>
</html>
\ No newline at end of file
<div metal:use-macro="load: ../main.pt">
<div metal:fill-slot="content">
<div class="well">
<div tal:content="structure form"/>
</div>
</div>
</div>
\ No newline at end of file
<div metal:use-macro="load: ../main.pt">
<div metal:fill-slot="content">
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title" i18n:translate="Warning">Warning</h3>
</div>
<div class="panel-body" i18n:translate="warning-delete-user">
Delete <span tal:replace="user.email" i18n:name="email"/>
ID <span tal:replace="user.id" i18n:name="uid"/> ?
</div>
</div>
<div tal:content="structure form"/>
</div>
</div>
<div metal:use-macro="load: ../main.pt">
<div metal:fill-slot="content">
<div class="well">
<div tal:content="structure form"/>
</div>
</div>
</div>
\ No newline at end of file
<div metal:use-macro="load: ../main.pt">
<!-- content -->
<div metal:fill-slot="content">
<div class="jarviswidget" style="border-top:1px solid #ccc!important">
<div role="content">
<table id="table1" class="table table-bordered table-hover table-condensed">
<thead>
<tr>
<th>ID</th>
<th>Email</th>
<th>User Name</th>
<th>Status</th>
<th>Last Login</th>
<th>Registered Date</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
<!-- end content -->
<script type="text/javascript" metal:fill-slot="scripts">var mID;
var mID;
var oTable;
var oTableUri = "${home}/user"
var oTableUrl = oTableUri + "/grid/act";
$(document).ready(function () {
oTable = $('#table1').DataTable({
dom: '<"row"<"col-md-8"<"toolbar">l><"col-md-4"f>>rtip',
processing: true,
serverSide: true,
ajax: oTableUrl,
stateSave: true,
scrollCollapse: true,
sort: true,
info: false,
filter: true,
autoWidth: false,
paginate: true,
paginationType: "full_numbers",
lengthMenu: [
[10, 25, 50, 100],
[10, 25, 50, 100]
],
columnDefs: [{
searchable: false,
visible: false,
targets: [0]
}],
columns: [{
"data": "id"
},
{
"data": "email",
"width": "200px",
"className": "text-left"
},
{
"data": "name"
},
{
"data": "status",
"width": "200px",
"className": "text-center",
"render": function (data, type, full, meta) {
if (data == 0) return 'NonAktif';
else if (data == 1) return 'Aktif';
else return "-";
}
},
{
"data": "last_login",
"width": "200px",
"className": "text-center"
},
{
"data": "registered",
"width": "200px",
"className": "text-center"
}
],
"language": {
"search": "Cari : ",
"paginate": {
"first": "Pertama ",
"last": "Akhir ",
"previous": "",
"next": "",
},
"lengthMenu": "Tampil _MENU_ baris "
},
});
var tb_array = [
'<div class="btn-group pull-left">',
' <button id="btn_view" class="btn btn btn-warning" type="button" data-toggle="tooltip" title="View"> <i class="fa fa-eye"></i></button>',
' <button tal:condition="has_permission(request, 'user-edit')" id="btn_add" class="btn btn btn-success" type="button" data-toggle="tooltip" title="Tambah"><i class="fa fa-plus"></i></button>',
' <button tal:condition="has_permission(request, 'user-edit')" id="btn_edit" class="btn btn btn-warning" type="button" data-toggle="tooltip" title="Koreksi"><i class="fa fa-edit"></i></button>',
' <button tal:condition="has_permission(request, 'user-edit')" id="btn_delete" class="btn btn btn-danger" type="button" data-toggle="tooltip" title="Hapus"><i class="fa fa-trash-o"></i></button>',
' <button id="btn_pdf" class="btn btn btn-primary" type="button" data-toggle="tooltip" title="PDF"><i class="fa fa-file-pdf-o"></i></button>',
' <button id="btn_csv" class="btn btn btn-primary" type="button" data-toggle="tooltip" title="CSV"><i class="fa fa-file-excel-o"></i></button>',
' <button id="btn_close" class="btn btn btn-warning" type="button" data-toggle="tooltip" title="Tutup"><i class="fa fa-arrow-right"></i></button>',
' &nbsp;',
'</div>',
];
var tb = tb_array.join(' ');
$("div.toolbar").html(tb);
$("div.toolbar").attr('style', 'display:block; float: left; margin-bottom:6px; line-height:16px;');
$('#table1 tbody').on('click', 'tr', function () {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
} else {
var aData = oTable.row(this).data();
oTable.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
mID = aData.id;
oTable.$('tr.row_selected').removeClass('row_selected');
$(this).addClass('row_selected');
}
});
$('#btn_add').click(function () {
window.location = oTableUri + '/add';
});
$('#btn_view').click(function () {
if (mID) window.location = oTableUri + '/' + mID + '/view';
else
$.SmartMessageBox({
title: "View",
content: "Pilih Baris yang akan di lihat...",
buttons: '[Ok]'
});
;
});
$('#btn_edit').click(function () {
if (mID) window.location = oTableUri + '/' + mID + '/edit';
else
$.SmartMessageBox({
title: "Edit",
content: "Pilih Baris yang akan di edit...",
buttons: '[Ok]'
});
;
});
$('#btn_delete').click(function () {
if (mID) window.location = oTableUri + '/' + mID + '/delete';
else
$.SmartMessageBox({
title: "Hapus",
content: "Pilih Baris yang akan di hapus...",
buttons: '[Ok]'
});
});
$('#btn_csv').click(function () {
url = oTableUri + "/csv/act";
window.open(url);
});
$('#btn_pdf').click(function () {
url = oTableUri + "/pdf/act";
window.open(url);
});
$("#btn_close").click(function () {
window.location = '/';
return false;
});
});
</script>
</div>
......@@ -2,21 +2,15 @@ import os
import re
import colander
import transaction
from datatables import (ColumnDT, DataTables, )
from deform import (Form, widget, ValidationFailure, Button, )
# from sqlalchemy.exc import IntegrityErrortpl
from sqlalchemy.exc import IntegrityError
from deform import (widget, )
from opensipkd.tools import create_now
from opensipkd.tools.buttons import btn_cancel, btn_save, btn_close
from opensipkd.tools.report import open_rml_row, csv_response, open_rml_pdf, pdf_response
from pyramid.httpexceptions import (HTTPFound, HTTPNotFound, )
from pyramid.i18n import TranslationStringFactory
from pyramid.view import view_config
from sqlalchemy import (func, or_, )
from sqlalchemy import (func, )
from ziggurat_foundations.models.services.user import UserService
from . import BaseView
from .company import company_widget
from .user_login import (
regenerate_security_code, send_email_security_code, generate_api_key, )
......@@ -25,14 +19,235 @@ from ..models import (DBSession, User, Group, UserGroup, ResCompany, )
_ = TranslationStringFactory('user')
########
# List #
########
@view_config(
route_name='user', renderer='templates/user/list.pt',
permission='user-view')
def view_list(request):
return dict()
class ListSchema(colander.Schema):
id = colander.SchemaNode(colander.String(), title="ID", visible=False, searchable=False)
email = colander.SchemaNode(colander.String())
user_name = colander.SchemaNode(colander.String())
status = colander.SchemaNode(colander.Integer(), width=50, searchable=False)
last_login = colander.SchemaNode(colander.String(), width=100, field="last_login_date", searchable=False)
registered = colander.SchemaNode(colander.String(), width=100, field="registered_date", searchable=False)
class Views(BaseView):
def __init__(self, request):
super(Views, self).__init__(request)
self.list_schema = ListSchema
self.list_route = 'user'
self.table = User
self.edit_schema = EditSchema
self.add_schema = AddSchema
self.list_buttons = self.list_buttons + self.list_report
def get_bindings(self, row=None):
status_list = (
('1', _('Active')),
('0', _('Archived')))
if row and row.api_key:
api_key_list = (
('', _(row.api_key)),
('0', _('Hapus')))
else:
api_key_list = (
('', _('Tidak ada')),
('1', _('Buatkan')))
group_list = get_group_list()
return dict(status_list=status_list,
group_list=group_list,
api_key_list=api_key_list,
user=row,
company_list=ResCompany.get_list())
@view_config(
route_name='user', renderer='templates/table.pt',
permission='user-view')
def view_list(self):
return super(Views, self).view_list()
@view_config(
route_name='user-act', renderer='json', permission='user-view')
def view_act(self):
return super(Views, self).view_act()
def next_act(self):
url_dict = self.req.matchdict
if url_dict['act'] == 'csv':
query = query_register()
row = query.first()
header = row.keys()
rows = [list(item) for item in query.all()]
filename = 'user.csv'
value = {
'header': header,
'rows': rows,
}
return csv_response(self.req, value, filename)
elif url_dict['act'] == 'pdf':
query = query_register()
import opensipkd.base
base_path = os.path.dirname(opensipkd.base.__file__)
path = os.path.join(base_path, 'reports')
rml_row = open_rml_row(path + '/user.row.rml')
rows = [rml_row.format(user_name=r.user_name, email=r.email,
registered_date=r.registered_date) for r in query.all()]
pdf, filename = open_rml_pdf(path + '/user.rml', rows=rows,
company=self.req.company,
departement=self.req.departement,
address=self.req.address,
base_path=base_path)
return pdf_response(self.req, pdf, filename)
def form_validator(self, form, value):
if "company_id" in value and not value["company_id"]:
value["company_id"] = None
def save_request(self, values, row=None):
request = self.req
values["email"] = values['email'].lower()
values["user_name"] = re.sub(' ', '', values['user_name']) # .lower()
values["security_code_date"] = create_now()
company_id = request.user and request.user.company_id or "company_id" in values and values["company_id"] or None
values["company_id"] = company_id
if 'is_api_key' in values:
values["api_key"] = generate_api_key()
insert = not row
row = self.save(values, self.req.user, row)
if insert:
remain = regenerate_security_code(row)
if 'password' in values:
data = dict(username=row.user_name)
ts = _(
'user-added-with-password',
default='${username} berhasil ditambahkan.', mapping=data)
else:
send_email_security_code(
self.req, row, remain, 'Welcome new user', 'email-new-user',
'email-new-user.tpl')
data = dict(email=row.email)
ts = _(
'user-added',
default='${email} berhasil ditambahkan dan email untuk ubah ' \
'kata kunci sudah dikirim.',
mapping=data)
self.ses.flash(ts)
if 'password' in values:
UserService.set_password(row, values['password'])
DBSession.add(row)
DBSession.flush()
existing = user_group_set(row)
unused = existing - values['groups']
if unused:
q = DBSession.query(UserGroup).filter_by(user_id=row.id).filter(
UserGroup.group_id.in_(unused))
q.delete(synchronize_session=False)
for gid in unused:
reduce_member_count(gid)
new = values['groups'] - existing
for gid in new:
ug = UserGroup()
ug.user_id = row.id
ug.group_id = gid
DBSession.add(ug)
add_member_count(gid)
return row
def after_add(self, row, values):
pass
@view_config(
route_name='user-add', renderer='templates/form.pt',
permission='user-view')
def view_add(self):
return super(Views, self).view_add()
# user, remain = insert(request, values)
def get_values(self, row, istime=False):
d = super(Views, self).get_values(row, istime)
d["groups"] = user_group_set(row)
return d
@view_config(
route_name='user-edit', renderer='templates/user/edit.pt',
permission='user-edit')
def view_edit(self):
return super(Views, self).view_edit()
# q = DBSession.query(User).filter_by(id=request.matchdict['id'])
# if request.user.company_id:
# q = q.filter_by(company_id=request.user.company_id)
# user = q.first()
# if not user:
# return HTTPNotFound()
# if user.id == request.user.id:
# form = get_form(request, AddSchema, user)
# else:
# if 'opensipkd.webr.models' in get_modules():
# form = get_form(request, EditSchema2, user)
# else:
# form = get_form(request, EditSchema, user)
# resp = dict(title=_('Edit user'))
# if not request.POST:
# d = user.to_dict()
# d['groups'] = user_group_set(user)
# resp['form'] = form.render(appstruct=d)
# return resp
# if 'save' not in request.POST:
# return HTTPFound(location=request.route_url('user'))
# items = request.POST.items()
# try:
# c = form.validate(items)
# except ValidationFailure:
# resp['form'] = form.render()
# return resp
# update(request, user, dict(c.items()))
# data = dict(username=user.user_name)
# ts = _('user-updated', default='${username} profile updated', mapping=data)
# request.session.flash(ts)
# return HTTPFound(location=request.route_url('user'))
@view_config(
route_name='user-view', renderer='templates/form.pt',
permission='user-view')
def view_view(self):
return super(Views, self).view_view()
@view_config(
route_name='user-delete', renderer='templates/form.pt',
permission='user-edit')
def view_delete(self):
return super(Views, self).view_delete()
def delete_msg(self, row):
data = dict(uid=row.id, email=row.email)
return _(
'user-deleted',
default='User ${email} ID ${uid} has been deleted',
mapping=data)
def before_delete(self, row):
gid_list = user_group_set(row)
for gid in gid_list:
reduce_member_count(gid)
def query_id(self):
q = DBSession.query(User).filter_by(id=self.req.matchdict['id'])
if self.req.user.company_id:
q = q.filter_by(company_id=self.req.user.company_id)
return q
#######
......@@ -90,7 +305,7 @@ REGEX_BEGIN_END_ALPHANUMERIC = re.compile('^[A-Za-z0-9]+(?:[-][A-Za-z0-9]+)*$')
class UsernameValidator(Validator):
def __call__(self, node, value):
username = value # .lower()
username = value
if self.user and self.user.user_name == username:
return
match = REGEX_ONLY_CONTAIN.search(username)
......@@ -109,6 +324,7 @@ class UsernameValidator(Validator):
found = q.first()
if not found:
return
data = dict(username=username, uid=found.id)
ts = _(
'username-already-used',
......@@ -127,14 +343,6 @@ def username_validator(node, kw):
return UsernameValidator(kw['user'])
def form_validator(form, value):
# new_password = value.get('new_password')
# retype_password = value.get('retype_password')
# if new_password != retype_password:
# raise colander.Invalid(form, _('Pengulangan kata kunci tidak sama'))
pass
def save_user(values, user, row=None):
if not row:
row = User()
......@@ -182,29 +390,6 @@ def get_group_list():
return r
def get_form(request, class_form, user=None, buttons=(btn_save, btn_cancel)):
status_list = (
('1', _('Active')),
('0', _('Archived')))
if user and user.api_key:
api_key_list = (
('', _(user.api_key)),
('0', _('Hapus')))
else:
api_key_list = (
('', _('Tidak ada')),
('1', _('Buatkan')))
schema = class_form(validator=form_validator)
group_list = get_group_list()
schema = schema.bind(
status_list=status_list, group_list=group_list, user=user,
api_key_list=api_key_list,
company_list=ResCompany.get_list()
)
return Form(schema, buttons=buttons)
def add_member_count(gid):
q = DBSession.query(Group).filter_by(id=gid)
group = q.first()
......@@ -219,78 +404,6 @@ def reduce_member_count(gid):
DBSession.add(group)
def insert(request, values):
user = User()
user.email = values['email'].lower()
user.user_name = re.sub(' ', '', values['user_name']) # .lower()
user.security_code_date = create_now()
company_id = request.user and request.user.company_id or "company_id" in values and values["company_id"] or None
user.company_id = company_id
remain = regenerate_security_code(user)
if 'is_api_key' in values:
user.api_key = generate_api_key()
if 'password' in values:
UserService.set_password(user, values['password'])
DBSession.add(user)
try:
DBSession.flush()
except IntegrityError as e:
transaction.abort()
user.user_name = user.email
DBSession.add(user)
DBSession.flush()
if 'groups' in values and values['groups']:
for gid in values['groups']:
ug = UserGroup()
ug.user_id = user.id
ug.group_id = gid
DBSession.add(ug)
add_member_count(gid)
return user, remain
@view_config(
route_name='user-add', renderer='templates/user/add.pt',
permission='user-view')
def view_add(request):
# if 'opensipkd.webr.models' in get_modules():
# form = get_form(request, AddSchema2)
# else:
form = get_form(request, AddSchema)
resp = dict(title=_('Add user'))
if not request.POST:
resp['form'] = form.render()
return resp
if 'save' not in request.POST:
return HTTPFound(location=request.route_url('user'))
items = request.POST.items()
try:
c = form.validate(items)
except ValidationFailure:
resp['form'] = form.render()
return resp
values = dict(c.items())
user, remain = insert(request, values)
if 'password' in values:
data = dict(username=user.user_name)
ts = _(
'user-added-with-password',
default='${username} berhasil ditambahkan.', mapping=data)
else:
send_email_security_code(
request, user, remain, 'Welcome new user', 'email-new-user',
'email-new-user.tpl')
data = dict(email=user.email)
ts = _(
'user-added',
default='${email} berhasil ditambahkan dan email untuk ubah ' \
'kata kunci sudah dikirim.',
mapping=data)
request.session.flash(ts)
return HTTPFound(location=request.route_url('user'))
def user_group_set(user):
q = DBSession.query(UserGroup).filter_by(user_id=user.id)
r = []
......@@ -299,188 +412,6 @@ def user_group_set(user):
return set(r)
def update(request, user, values):
user.email = values['email'].lower()
user.user_name = re.sub(' ', '', values['user_name']) # .lower())
if user.id != request.user.id:
user.status = values['status']
is_api_key = values.get('is_api_key')
if is_api_key == '0':
user.api_key = None
elif is_api_key == '1':
user.api_key = generate_api_key()
if 'password' in values:
UserService.set_password(user, values['password'])
company_id = request.user.company_id or 'company_id' in values and values["company_id"] or None
user.company_id = company_id
DBSession.add(user)
existing = user_group_set(user)
unused = existing - values['groups']
if unused:
q = DBSession.query(UserGroup).filter_by(user_id=user.id).filter(
UserGroup.group_id.in_(unused))
q.delete(synchronize_session=False)
for gid in unused:
reduce_member_count(gid)
new = values['groups'] - existing
for gid in new:
ug = UserGroup()
ug.user_id = user.id
ug.group_id = gid
DBSession.add(ug)
add_member_count(gid)
@view_config(
route_name='user-edit', renderer='templates/user/edit.pt',
permission='user-edit')
def view_edit(request):
q = DBSession.query(User).filter_by(id=request.matchdict['id'])
if request.user.company_id:
q = q.filter_by(company_id=request.user.company_id)
user = q.first()
if not user:
return HTTPNotFound()
if user.id == request.user.id:
form = get_form(request, AddSchema, user)
else:
# if 'opensipkd.webr.models' in get_modules():
# form = get_form(request, EditSchema2, user)
# else:
form = get_form(request, EditSchema, user)
resp = dict(title=_('Edit user'))
if not request.POST:
d = user.to_dict()
d['groups'] = user_group_set(user)
resp['form'] = form.render(appstruct=d)
return resp
if 'save' not in request.POST:
return HTTPFound(location=request.route_url('user'))
items = request.POST.items()
try:
c = form.validate(items)
except ValidationFailure:
resp['form'] = form.render()
return resp
update(request, user, dict(c.items()))
data = dict(username=user.user_name)
ts = _('user-updated', default='${username} profile updated', mapping=data)
request.session.flash(ts)
return HTTPFound(location=request.route_url('user'))
@view_config(
route_name='user-view', renderer='templates/user/edit.pt',
permission='user-view')
def view_view(request):
q = DBSession.query(User).filter_by(id=request.matchdict['id'])
if request.user.company_id:
q = q.filter_by(company_id=request.user.company_id)
user = q.first()
if not user:
return HTTPNotFound()
if user.id == request.user.id:
form = get_form(request, AddSchema, user)
else:
form = get_form(request, EditSchema, user, buttons=(btn_close,))
resp = dict(title=_('View user'))
if not request.POST:
d = user.to_dict()
d['groups'] = user_group_set(user)
resp['form'] = form.render(appstruct=d, readonly=True)
return resp
return HTTPFound(location=request.route_url('user'))
@view_config(
route_name='user-delete', renderer='templates/user/delete.pt',
permission='user-edit')
def view_delete(request):
q = DBSession.query(User).filter_by(id=request.matchdict['id'])
if request.user.company_id:
q = q.filter_by(company_id=request.user.company_id)
user = q.first()
if not user:
return HTTPNotFound()
if not request.POST:
btn_delete = Button('delete', _('Delete'))
btn_cancel = Button('cancel', _('Cancel'))
buttons = (btn_delete, btn_cancel)
form = Form(colander.Schema(), buttons=buttons)
return dict(title=_('Delete user'), user=user, form=form.render())
if 'delete' not in request.POST:
return HTTPFound(location=request.route_url('user'))
gid_list = user_group_set(user)
for gid in gid_list:
reduce_member_count(gid)
data = dict(uid=user.id, email=user.email)
ts = _(
'user-deleted',
default='User ${email} ID ${uid} has been deleted',
mapping=data)
q.delete()
request.session.flash(ts)
return HTTPFound(location=request.route_url('user'))
@view_config(
route_name='user-act', renderer='json', permission='user-view')
def view_act(request):
req = request
url_dict = req.matchdict
if url_dict['act'] == 'grid':
columns = [
ColumnDT(User.id, mData='id'),
ColumnDT(User.email, mData='email'),
ColumnDT(User.user_name, mData='name'),
ColumnDT(User.status, mData='status'),
ColumnDT(func.to_char(User.last_login_date, 'DD-MM-YYYY HH24:MI:SS'),
mData='last_login'),
ColumnDT(func.to_char(User.registered_date, 'DD-MM-YYYY HH24:MI:SS'),
mData='registered'),
]
query = DBSession.query().select_from(User)
if request.user.company_id:
query = query.filter(User.company_id == request.user.company_id)
row_table = DataTables(req.GET, query, columns)
return row_table.output_result()
elif url_dict['act'] == 'csv':
query = query_register()
row = query.first()
header = row.keys()
rows = []
for item in query.all():
rows.append(list(item))
filename = 'user.csv'
value = {
'header': header,
'rows': rows,
}
return csv_response(request, value, filename)
elif url_dict['act'] == 'pdf':
# todo ganti rml jadi openoffice
query = query_register()
_here = os.path.dirname(__file__) # get current folder -> views
path = os.path.dirname(_here) # mundur 1 level
path = os.path.join(path, 'reports')
rml_row = open_rml_row(path + '/user.row.rml')
rows = []
for r in query.all():
s = rml_row.format(user_name=r.user_name, email=r.email,
registered_date=r.registered_date)
rows.append(s)
pdf, filename = open_rml_pdf(path + '/user.rml', rows=rows,
company=request.company,
departement=request.departement,
address=request.address)
return pdf_response(request, pdf, filename)
def query_register():
return DBSession.query(User.user_name, User.email,
func.to_char(User.registered_date, "DD-MM-YYYY").label("registered_date")).order_by(
......
import os
import re
import colander
import transaction
from datatables import (ColumnDT, DataTables, )
from deform import (Form, widget, ValidationFailure, Button, )
# from sqlalchemy.exc import IntegrityErrortpl
from sqlalchemy.exc import IntegrityError
from opensipkd.tools import create_now
from opensipkd.tools.buttons import btn_cancel, btn_save, btn_close, btn_delete, btn_view
from opensipkd.tools.report import open_rml_row, csv_response, open_rml_pdf, pdf_response
from pyramid.httpexceptions import (HTTPFound, HTTPNotFound, )
from deform import (widget, )
from opensipkd.tools.buttons import btn_close, btn_delete, btn_view
from pyramid.i18n import TranslationStringFactory
from pyramid.view import view_config
from sqlalchemy import (func, or_, )
from ziggurat_foundations.models.services.user import UserService
from . import BaseView
from .company import company_widget
from .user_login import (
regenerate_security_code, send_email_security_code, generate_api_key, )
from ..models import (DBSession, User, Group, UserGroup, ResCompany, ExternalIdentity)
from ..models import (DBSession, User, ExternalIdentity)
_ = TranslationStringFactory('user')
########
# List #
########
class AddSchema(colander.Schema):
external_user_name = colander.SchemaNode(
colander.String(), title=_('User Name'))
......@@ -43,7 +25,7 @@ class EditSchema(AddSchema):
class ListSchema(colander.Schema):
id = colander.SchemaNode(colander.String())
id = colander.SchemaNode(colander.String(), field="external_id")
external_user_name = colander.SchemaNode(
colander.String(), title=_('User Name'))
provider_name = (colander.SchemaNode(colander.String(), title=_('Provider')))
......@@ -55,13 +37,12 @@ class UserExt(BaseView):
super(UserExt, self).__init__(request)
self.edit_schema = EditSchema
self.list_schema = ListSchema
# self.list_url = "/user/ext"
self.list_route = "user-ext"
self.list_buttons = (btn_view, btn_delete, btn_close)
self.table = ExternalIdentity
@view_config(
route_name='user-ext', renderer='templates/form_input.pt',
route_name='user-ext', renderer='templates/table.pt',
permission='user-view')
def view_list(self):
form = super(UserExt, self).view_list()
......@@ -82,56 +63,10 @@ class UserExt(BaseView):
@view_config(
route_name='user-ext-act', renderer='json', permission='user-view')
def view_act(self):
req = self.req
url_dict = req.matchdict
if url_dict['act'] == 'grid':
columns = [
ColumnDT(ExternalIdentity.external_id, mData='id'),
ColumnDT(ExternalIdentity.external_user_name, mData='external_user_name'),
ColumnDT(ExternalIdentity.provider_name, mData='provider_name'),
ColumnDT(ExternalIdentity.local_user_id, mData='local_user_id'),
]
query = DBSession.query().select_from(ExternalIdentity). \
outerjoin(User, User.id == ExternalIdentity.local_user_id)
if self.req.user.company_id:
query = query.filter(User.company_id == self.req.user.company_id)
row_table = DataTables(req.GET, query, columns)
return row_table.output_result()
return super(UserExt, self).view_act()
def delete_msg(self, row):
return f'Data ID {row.external_id} sudah dihapus.'
def query_id(self):
return DBSession.query(ExternalIdentity).filter_by(external_id=self.req.matchdict["id"])
# elif url_dict['act'] == 'csv':
# query = query_register()
# row = query.first()
# header = row.keys()
# rows = []
# for item in query.all():
# rows.append(list(item))
#
# filename = 'user.csv'
# value = {
# 'header': header,
# 'rows': rows,
# }
# return csv_response(request, value, filename)
# elif url_dict['act'] == 'pdf':
# # todo ganti rml jadi openoffice
# query = query_register()
# _here = os.path.dirname(__file__) # get current folder -> views
# path = os.path.dirname(_here) # mundur 1 level
# path = os.path.join(path, 'reports')
# rml_row = open_rml_row(path + '/user.row.rml')
# rows = []
# for r in query.all():
# s = rml_row.format(user_name=r.user_name, email=r.email,
# registered_date=r.registered_date)
# rows.append(s)
# pdf, filename = open_rml_pdf(path + '/user.rml', rows=rows,
# company=request.company,
# departement=request.departement,
# address=request.address)
# return pdf_response(request, pdf, filename)
# import os
# import re
# from sqlalchemy import (
# func,
# or_,
# )
# from pyramid.i18n import TranslationStringFactory
# from pyramid.view import view_config
# from pyramid.httpexceptions import (
# HTTPFound,
# HTTPNotFound,
# )
# import colander
# from deform import (
# Form,
# widget,
# ValidationFailure,
# Button,
# )
# from ziggurat_foundations.models.services.user import UserService
# from ..models import (
# DBSession,
# User,
# Group,
# UserGroup,
# )
# from datatables import (
# ColumnDT,
# DataTables,
# )
# from ..tools import create_now
# from ..tools.report import open_rml_row, csv_response, open_rml_pdf, pdf_response
# from . import (
# regenerate_security_code,
# send_email_security_code,
# generate_api_key,
# )
#
# _ = TranslationStringFactory('user')
#
#
# ########
# # List #
# ########
# @view_config(
# route_name='user', renderer='templates/user/list.pt',
# permission='user-view')
# def view_list(request):
# return dict()
#
#
# #######
# # Add #
# #######
# @colander.deferred
# def status_widget(node, kw):
# values = kw.get('status_list', [])
# return widget.SelectWidget(values=values)
#
#
# @colander.deferred
# def group_widget(node, kw):
# values = kw.get('group_list', [])
# return widget.CheckboxChoiceWidget(values=values)
#
#
# @colander.deferred
# def api_key_widget(node, kw):
# values = kw.get('api_key_list', [])
# return widget.SelectWidget(values=values)
#
#
# class Validator:
# def __init__(self, user):
# self.user = user
#
#
# class EmailValidator(colander.Email, Validator):
# def __init__(self, user):
# colander.Email.__init__(self)
# Validator.__init__(self, user)
#
# def __call__(self, node, value):
# if self.match_object.match(value) is None:
# raise colander.Invalid(node, _('Invalid email format'))
# email = value.lower()
# if self.user and self.user.email == email:
# return
# q = DBSession.query(User).filter_by(email=email)
# found = q.first()
# if not found:
# return
# data = dict(email=email, uid=found.id)
# ts = _(
# 'email-already-used',
# default='Email ${email} already used by user ID ${uid}',
# mapping=data)
# raise colander.Invalid(node, ts)
#
#
# REGEX_ONLY_CONTAIN = re.compile('([a-z0-9-]*)')
# REGEX_BEGIN_END_ALPHANUMERIC = re.compile('^[a-z0-9]+(?:[-][a-z0-9]+)*$')
#
#
# class UsernameValidator(Validator):
# def __call__(self, node, value):
# username = value.lower()
# if self.user and self.user.user_name == username:
# return
# match = REGEX_ONLY_CONTAIN.search(username)
# if not match or match.group(1) != username or username != value:
# ts = _(
# 'username-only-contain',
# default='Only a-z, 0-9, and - characters are allowed')
# raise colander.Invalid(node, ts)
# match = REGEX_BEGIN_END_ALPHANUMERIC.search(username)
# if not match:
# ts = _(
# 'username-first-end-alphanumeric',
# default='Only a-z or 0-9 at the start and end')
# raise colander.Invalid(node, ts)
# q = DBSession.query(User).filter_by(user_name=username)
# found = q.first()
# if not found:
# return
# data = dict(username=username, uid=found.id)
# ts = _(
# 'username-already-used',
# default='Username ${username} already used by ID ${uid}',
# mapping=data)
# raise colander.Invalid(node, ts)
#
#
# @colander.deferred
# def email_validator(node, kw):
# return EmailValidator(kw['user'])
#
#
# @colander.deferred
# def username_validator(node, kw):
# return UsernameValidator(kw['user'])
#
#
# def form_validator(form, value):
# new_password = value.get('new_password')
# retype_password = value.get('retype_password')
# if new_password != retype_password:
# raise colander.Invalid(form, _('Pengulangan kata kunci tidak sama'))
#
#
# # save_user ngambil dari base lama
# def save_user(values, user, row=None):
# if not row:
# row = User()
# row.from_dict(values)
# if 'password' in values and values['password']:
# row.password = values['password']
# # row.rpc_password = values['password']
#
# DBSession.add(row)
# DBSession.flush()
# return row
#
#
# class AddSchema(colander.Schema):
# email = colander.SchemaNode(
# colander.String(), title=_('Email'),
# validator=email_validator)
# user_name = colander.SchemaNode(colander.String(), title=_('Username'),
# validator=username_validator)
# groups = colander.SchemaNode(
# colander.Set(), widget=group_widget, title=_('Group'))
# is_api_key = colander.SchemaNode(
# colander.String(), widget=api_key_widget, title=_('API Key'),
# missing=colander.drop)
# new_password = colander.SchemaNode(
# colander.String(), widget=widget.PasswordWidget(),
# missing=colander.drop, title=_('Kata kunci'))
# retype_password = colander.SchemaNode(
# colander.String(), widget=widget.PasswordWidget(),
# missing=colander.drop, title=_('Ulangi kata kunci'))
#
#
# class EditSchema(AddSchema):
# status = colander.SchemaNode(
# colander.String(), widget=status_widget, title=_('Status'))
#
#
# def get_group_list():
# r = []
# q = DBSession.query(Group).order_by(Group.group_name)
# for row in q:
# g = (str(row.id), _(row.group_name))
# r.append(g)
# return r
#
#
# def get_form(request, class_form, user=None):
# status_list = (
# ('1', _('Active')),
# ('0', _('Inactive')))
# if user and user.api_key:
# api_key_list = (
# ('', _('Sudah ada')),
# ('0', _('Hapus')))
# else:
# api_key_list = (
# ('', _('Tidak ada')),
# ('1', _('Buatkan')))
# group_list = get_group_list()
# schema = class_form(validator=form_validator)
# schema = schema.bind(
# status_list=status_list, group_list=group_list, user=user,
# api_key_list=api_key_list)
# btn_save = Button('save', _('Simpan'))
# btn_cancel = Button('cancel', _('Batal'))
# return Form(schema, buttons=(btn_save, btn_cancel))
#
#
# def add_member_count(gid):
# q = DBSession.query(Group).filter_by(id=gid)
# group = q.first()
# group.member_count += 1
# DBSession.add(group)
#
#
# def reduce_member_count(gid):
# q = DBSession.query(Group).filter_by(id=gid)
# group = q.first()
# group.member_count -= 1
# DBSession.add(group)
#
#
# def insert(values):
# user = User()
# user.email = values['email'].lower()
# user.user_name = values['user_name'].lower()
# user.security_code_date = create_now()
# remain = regenerate_security_code(user)
# if 'is_api_key' in values:
# user.api_key = generate_api_key()
# if 'new_password' in values:
# UserService.set_password(user, values['new_password'])
# DBSession.add(user)
# DBSession.flush()
# if 'groups' in values and values['groups']:
# for gid in values['groups']:
# ug = UserGroup(user_id=user.id, group_id=gid)
# DBSession.add(ug)
# add_member_count(gid)
# return user, remain
#
#
# @view_config(
# route_name='user-add', renderer='templates/user/add.pt',
# permission='user-add')
# def view_add(request):
# form = get_form(request, AddSchema)
# resp = dict(title=_('Add user'))
# if not request.POST:
# resp['form'] = form.render()
# return resp
# if 'save' not in request.POST:
# return HTTPFound(location=request.route_url('user'))
# items = request.POST.items()
# try:
# c = form.validate(items)
# except ValidationFailure:
# resp['form'] = form.render()
# return resp
# values = dict(c.items())
# user, remain = insert(values)
# if 'new_password' in values:
# data = dict(username=user.user_name)
# ts = _(
# 'user-added-with-password',
# default='${username} berhasil ditambahkan.', mapping=data)
# else:
# send_email_security_code(
# request, user, remain, 'Welcome new user', 'email-new-user',
# 'email-new-user.tpl')
# data = dict(email=user.email)
# ts = _(
# 'user-added',
# default='${email} berhasil ditambahkan dan email untuk ubah ' \
# 'kata kunci sudah dikirim.',
# mapping=data)
# request.session.flash(ts)
# return HTTPFound(location=request.route_url('user'))
#
#
# ########
# # Edit #
# ########
# def user_group_set(user):
# q = DBSession.query(UserGroup).filter_by(user_id=user.id)
# r = []
# for ug in q:
# r.append(str(ug.group_id))
# return set(r)
#
#
# def update(request, user, values):
# fnames = ['email', 'user_name']
# user.email = values['email'].lower()
# user.user_name = values['user_name'].lower()
# if user.id != request.user.id:
# user.status = values['status']
# is_api_key = values.get('is_api_key')
# if is_api_key == '0':
# user.api_key = None
# elif is_api_key == '1':
# user.api_key = generate_api_key()
# if 'new_password' in values:
# UserService.set_password(user, values['new_password'])
# DBSession.add(user)
# existing = user_group_set(user)
# unused = existing - values['groups']
# if unused:
# q = DBSession.query(UserGroup).filter_by(user_id=user.id).filter(
# UserGroup.group_id.in_(unused))
# q.delete(synchronize_session=False)
# for gid in unused:
# reduce_member_count(gid)
# new = values['groups'] - existing
# for gid in new:
# ug = UserGroup(user_id=user.id, group_id=gid)
# DBSession.add(ug)
# add_member_count(gid)
#
#
# @view_config(
# route_name='user-edit', renderer='templates/user/edit.pt',
# permission='user-edit')
# def view_edit(request):
# q = DBSession.query(User).filter_by(id=request.matchdict['id'])
# user = q.first()
# if not user:
# return HTTPNotFound()
# if user.id == request.user.id:
# form = get_form(request, AddSchema, user)
# else:
# form = get_form(request, EditSchema, user)
# resp = dict(title=_('Edit user'))
# if not request.POST:
# d = user.to_dict()
# d['groups'] = user_group_set(user)
# resp['form'] = form.render(appstruct=d)
# return resp
# if 'save' not in request.POST:
# return HTTPFound(location=request.route_url('user'))
# items = request.POST.items()
# try:
# c = form.validate(items)
# except ValidationFailure:
# resp['form'] = form.render()
# return resp
# update(request, user, dict(c.items()))
# data = dict(username=user.user_name)
# ts = _('user-updated', default='${username} profile updated', mapping=data)
# request.session.flash(ts)
# return HTTPFound(location=request.route_url('user'))
#
#
# ##########
# # Delete #
# ##########
# @view_config(
# route_name='user-delete', renderer='templates/user/delete.pt',
# permission='user-edit')
# def view_delete(request):
# q = DBSession.query(User).filter_by(id=request.matchdict['id'])
# user = q.first()
# if not user:
# return HTTPNotFound()
# if not request.POST:
# btn_delete = Button('delete', _('Delete'))
# btn_cancel = Button('cancel', _('Cancel'))
# buttons = (btn_delete, btn_cancel)
# form = Form(colander.Schema(), buttons=buttons)
# return dict(title=_('Delete user'), user=user, form=form.render())
# if 'delete' not in request.POST:
# return HTTPFound(location=request.route_url('user'))
# gid_list = user_group_set(user)
# for gid in gid_list:
# reduce_member_count(gid)
# data = dict(uid=user.id, email=user.email)
# ts = _(
# 'user-deleted',
# default='User ${email} ID ${uid} has been deleted',
# mapping=data)
# q.delete()
# request.session.flash(ts)
# return HTTPFound(location=request.route_url('user'))
#
#
# ##########
# # Action #
# ##########
# @view_config(
# route_name='user-act', renderer='json', permission='user-view')
# def view_act(request):
# ses = request.session
# req = request
# params = req.params
# url_dict = req.matchdict
# if url_dict['act'] == 'grid':
# columns = [
# ColumnDT(User.id, mData='id'),
# ColumnDT(User.email, mData='email'),
# ColumnDT(User.user_name, mData='name'),
# ColumnDT(User.status, mData='status'), # , filter=_DTstatus
# ColumnDT(func.to_char(User.last_login_date, 'DD-MM-YYYY HH24:MI:SS'), mData='last_login'),
# ColumnDT(func.to_char(User.registered_date, 'DD-MM-YYYY HH24:MI:SS'), mData='registered'),
# ]
# query = DBSession.query().select_from(User)
# rowTable = DataTables(req.GET, query, columns)
# return rowTable.output_result()
# elif url_dict['act'] == 'hon':
# term = 'term' in params and params['term'] or ''
# rows = DBSession.query(User.id, User.user_name, User.email.label('value')
# ).filter(
# User.id > 1,
# or_(User.email.ilike('%%%s%%' % term),
# User.user_name.ilike('%%%s%%' % term))
# ).all()
# r = []
# for k in rows:
# d = dict(id=k[0],
# value=k[1] + '(' + k[2] + ')')
# r.append(d)
# return r
# elif url_dict['act'] == 'hom':
# term = 'term' in params and params['term'] or ''
# rows = DBSession.query(User.id, User.email
# ).filter(User.id != '1',
# User.id != '2',
# User.email.ilike('%%%s%%' % term)
# ).all()
# r = []
# for k in rows:
# d = dict(id=k[0],
# value=k[1],
# kode=k[1],
# nama=k[2])
# r.append(d)
# return r
# elif url_dict['act'] == 'csv':
# query = query_register()
# row = query.first()
# header = row.keys()
# rows = []
# for item in query.all():
# rows.append(list(item))
#
# filename = 'user.csv'
# value = {
# 'header': header,
# 'rows': rows,
# }
# return csv_response(request, value, filename)
# elif url_dict['act'] == 'pdf':
# query = query_register()
# _here = os.path.dirname(__file__) # get current folder -> views
# path = os.path.dirname(_here) # mundur 1 level
# path = os.path.join(path, 'reports')
# rml_row = open_rml_row(path + '/user.row.rml')
# rows = []
# for r in query.all():
# s = rml_row.format(user_name=r.user_name, email=r.email,
# registered_date=r.registered_date)
# rows.append(s)
# pdf, filename = open_rml_pdf(path + '/user.rml', rows=rows,
# company=request.company,
# departement=request.departement,
# address=request.address)
# return pdf_response(request, pdf, filename)
#
#
# #######
# # RPT #
# #######
# def query_register():
# return DBSession.query(User.user_name, User.email,
# func.to_char(User.registered_date, "DD-MM-YYYY").label("registered_date")).order_by(
# User.user_name)
......@@ -116,7 +116,7 @@ class DeTable(field.Field):
btn_view_js = "{window.location = o%sUri+'/'+m%sID+'/view%s';}" % (tableid, tableid, params)
btn_delete_js = "{window.location = o%sUri+'/'+m%sID+'/delete%s';}" % (tableid, tableid, params)
btn_csv_js = "{window.location = o%sUri+'/csv/act%s';}" % (tableid, params)
btn_pdf_js = "{window.location = o%sUri+'/pdf/act%s';}" % (tableid, params)
btn_pdf_js = "{window.open(o%sUri+'/pdf/act%s');}" % (tableid, params)
action_suffix=f"{action_suffix}{params}"
field.Field.__init__(self, schema, **kw)
_buttons = []
......
......@@ -19,7 +19,6 @@ from deform.widget import MappingWidget
from deform.compat import text_
from .i18n import _
_BLANK = text_("")
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!