Commit 8b26ab2b by taufikyu

Merge branch 'latest' of https://git.opensipkd.com/aa.gusti/opensipkd-base into latest

2 parents 278b71c4 575f7515
Showing 58 changed files with 1750 additions and 374 deletions
...@@ -15,14 +15,14 @@ Biasanya pada home directory:: ...@@ -15,14 +15,14 @@ Biasanya pada home directory::
$ ~/env/bin/pip install --upgrade pip setuptools $ ~/env/bin/pip install --upgrade pip setuptools
$ ~/env/bin/pip install wheel $ ~/env/bin/pip install wheel
##Instalasi ## Instalasi
###Production: ### Production:
$ ~/env/bin/pip install git+https://git.opensipkd.com/aa.gusti/base.git@latest $ ~/env/bin/pip install git+https://git.opensipkd.com/aa.gusti/base.git@latest
$ cp ~/env/etc/live_opensipkd.tpl ~/env/etc/live_opensipkd.ini $ cp ~/env/etc/live_opensipkd.tpl ~/env/etc/live_opensipkd.ini
###Install Development:: ### Install Development::
$ source ~/env/bin/activate $ source ~/env/bin/activate
$ mkdir apps $ mkdir apps
$ cd apps $ cd apps
...@@ -30,11 +30,11 @@ Biasanya pada home directory:: ...@@ -30,11 +30,11 @@ Biasanya pada home directory::
$ env/bin/pip install -e base[dev] $ env/bin/pip install -e base[dev]
$ cp ~/env/etc/test_opensipkd.tpl ~/env/etc/test_opensipkd.ini $ cp ~/env/etc/test_opensipkd.tpl ~/env/etc/test_opensipkd.ini
##Sesuaikan konfigurasi ## Sesuaikan konfigurasi
Konfigurasi tergantung pada jenis instalasi ``test_opensipkd.ini`` atau Konfigurasi tergantung pada jenis instalasi ``test_opensipkd.ini`` atau
``live_opensipkd.ini``pada baris berikut ini:: ``live_opensipkd.ini``pada baris berikut ini::
###Database Koneksi: ### Database Koneksi:
[app:main] [app:main]
sqlalchemy.url = postgresql://user:password@localhost:5432/db sqlalchemy.url = postgresql://user:password@localhost:5432/db
session.url = postgresql://user:password@localhost:5432/db session.url = postgresql://user:password@localhost:5432/db
...@@ -48,7 +48,7 @@ Konfigurasi tergantung pada jenis instalasi ``test_opensipkd.ini`` atau ...@@ -48,7 +48,7 @@ Konfigurasi tergantung pada jenis instalasi ``test_opensipkd.ini`` atau
sqlalchemy.url = postgresql://user:password@localhost:5432/db sqlalchemy.url = postgresql://user:password@localhost:5432/db
script_location = opensipkd.base:alembic script_location = opensipkd.base:alembic
###Login/Register: ### Login/Register:
[app:main] [app:main]
captcha_files= captcha_files=
# static folder untuk image captcha # static folder untuk image captcha
...@@ -65,7 +65,7 @@ Konfigurasi tergantung pada jenis instalasi ``test_opensipkd.ini`` atau ...@@ -65,7 +65,7 @@ Konfigurasi tergantung pada jenis instalasi ``test_opensipkd.ini`` atau
# diisi nama template login apabila akan menggunakan template yang berbeda # diisi nama template login apabila akan menggunakan template yang berbeda
###Handling Log File: ### Handling Log File:
Logging dapat dilakukan console, file atau tabel Logging dapat dilakukan console, file atau tabel
...@@ -100,7 +100,7 @@ Logging dapat dilakukan console, file atau tabel ...@@ -100,7 +100,7 @@ Logging dapat dilakukan console, file atau tabel
sqlalchemy.url = postgresql://user:password@localhost:5432/db sqlalchemy.url = postgresql://user:password@localhost:5432/db
script_location = alembic script_location = alembic
``` ```
###Google Integrated dan Custom Register Form ### Google Integrated dan Custom Register Form
Aplikasi sudah bisa terintegrsi dengan google oauth2 Aplikasi sudah bisa terintegrsi dengan google oauth2
Konfigurasi merupakan bagian dari "main" Konfigurasi merupakan bagian dari "main"
...@@ -112,7 +112,7 @@ Konfigurasi merupakan bagian dari "main" ...@@ -112,7 +112,7 @@ Konfigurasi merupakan bagian dari "main"
``` ```
##Buat tabelnya:: ## Buat tabelnya::
Perintah untuk membuat tabel Perintah untuk membuat tabel
......
...@@ -40,7 +40,7 @@ from opensipkd.tools import ( ...@@ -40,7 +40,7 @@ from opensipkd.tools import (
from deform import ZPTRendererFactory, Form from deform import ZPTRendererFactory, Form
from pkg_resources import resource_filename from pkg_resources import resource_filename
from deform.widget import default_resource_registry
import os import os
from opensipkd.models.handlers import LogDBSession from opensipkd.models.handlers import LogDBSession
...@@ -148,6 +148,7 @@ def add_global(event): ...@@ -148,6 +148,7 @@ def add_global(event):
event['allow_register'] = allow_register event['allow_register'] = allow_register
event['change_unit'] = change_unit event['change_unit'] = change_unit
event['get_params'] = get_params event['get_params'] = get_params
event['get_urls'] = get_urls
def get_params(params, alternate=None, settings=None): def get_params(params, alternate=None, settings=None):
...@@ -380,15 +381,18 @@ def json_rpc(): ...@@ -380,15 +381,18 @@ def json_rpc():
# if user is not None: # if user is not None:
# return user.id # return user.id
def get_urls(url):
home = get_params('_host', "")
if home:
urls = url.split(":")
homes = home.split(":")
if urls[0] != homes[0]:
return ":".join([homes[0], ":".join(urls[1:])])
return url
def get_host(request): def get_host(request):
host = get_params('_host', "") host = get_params('_host', "")
# if not host:
# host = request.route_url('home')[:-1]
# proto = 'HTTP_X_FORWARDED_PROTO' in request.environ \
# and request.environ['HTTP_X_FORWARDED_PROTO'] \
# or "http"
# host = f"{proto}://{request.host}"
return host and host or get_home(request) return host and host or get_home(request)
...@@ -419,8 +423,11 @@ partner_idcard_url = 'partner/idcard' ...@@ -419,8 +423,11 @@ partner_idcard_url = 'partner/idcard'
def main(global_config, **settings): def main(global_config, **settings):
""" This function returns a Pyramid WSGI application. """ This function returns a Pyramid WSGI application.
""" """
default_resource_registry.registry['jquery.maskMoney'] = {
None: {"js": "opensipkd.base:static/jquery/jquery.maskMoney.min.js"}}
engine = engine_from_config(settings, 'sqlalchemy.') engine = engine_from_config(
settings, 'sqlalchemy.', client_encoding='utf8', convert_unicode=True)
DBSession.configure(bind=engine) DBSession.configure(bind=engine)
LogDBSession.configure(bind=engine) LogDBSession.configure(bind=engine)
Base.metadata.bind = engine Base.metadata.bind = engine
...@@ -467,7 +474,8 @@ def main(global_config, **settings): ...@@ -467,7 +474,8 @@ def main(global_config, **settings):
config.add_request_method(thousand, 'thousand', reify=True) config.add_request_method(thousand, 'thousand', reify=True)
config.add_request_method(is_devel, 'devel', reify=True) config.add_request_method(is_devel, 'devel', reify=True)
config.add_request_method(get_host, '_host', reify=True) config.add_request_method(get_host, '_host', reify=True)
config.add_request_method(get_home, 'home', reify=True) config.add_request_method(get_host, 'home', reify=True)
# config.add_request_method(get_urls, 'route_urls', reify=True)
config.add_request_method(google_signin_client_id, config.add_request_method(google_signin_client_id,
'google_signin_client_id', reify=True) 'google_signin_client_id', reify=True)
config.add_request_method(google_signin_client_ids, config.add_request_method(google_signin_client_ids,
......
Generic single-database configuration.
\ No newline at end of file \ No newline at end of file
Generic single-database configuration.
alembic -c config -n section_name revision -m "notes "
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.20.0-2bc7ab61c56f459e8176eb05c7705e145cd400ad -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="users" language="groovy" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="cc1a9dab-bb8a-4181-94ac-73c3dc91137c">
<property name="ireport.zoom" value="1.3310000000000004"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="New Data Adapter"/>
<queryString>
<![CDATA[SELECT * FROM users]]>
</queryString>
<field name="userid" class="java.lang.String"/>
<field name="nama" class="java.lang.String"/>
<field name="created" class="java.sql.Timestamp"/>
<field name="disabled" class="java.lang.Integer"/>
<field name="passwd" class="java.lang.String"/>
<field name="id" class="java.lang.Integer"/>
<field name="kd_kantor" class="java.lang.String"/>
<field name="kd_kanwil" class="java.lang.String"/>
<field name="kd_tp" class="java.lang.String"/>
<field name="kd_kanwil_bank" class="java.lang.String"/>
<field name="kd_kppbb_bank" class="java.lang.String"/>
<field name="kd_bank_tunggal" class="java.lang.String"/>
<field name="kd_bank_persepsi" class="java.lang.String"/>
<field name="nip" class="java.lang.String"/>
<field name="jabatan" class="java.lang.String"/>
<field name="handphone" class="java.lang.String"/>
<field name="token" class="java.lang.String"/>
<field name="security_code" class="java.lang.String"/>
<field name="last_login_date" class="java.sql.Timestamp"/>
<field name="user_name" class="java.lang.String"/>
<field name="user_password" class="java.lang.String"/>
<field name="email" class="java.lang.String"/>
<field name="status" class="java.lang.Integer"/>
<field name="registered_date" class="java.sql.Timestamp"/>
<field name="security_code_date" class="java.sql.Timestamp"/>
<field name="api_key" class="java.lang.String"/>
<field name="partner_id" class="java.lang.Integer"/>
<field name="company_id" class="java.lang.Integer"/>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="21" splitType="Stretch"/>
</title>
<pageHeader>
<band height="35" splitType="Stretch"/>
</pageHeader>
<columnHeader>
<band height="20" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="100" height="20" uuid="45c2cace-4a3f-495c-9002-be2f2ac8eca4"/>
<textElement>
<font isBold="true" isUnderline="true"/>
</textElement>
<text><![CDATA[User Name]]></text>
</staticText>
<staticText>
<reportElement x="100" y="0" width="255" height="20" uuid="3a03e8b0-96f7-4754-b00e-ceae1a0e5aa9"/>
<textElement>
<font isBold="true" isUnderline="true"/>
</textElement>
<text><![CDATA[Email]]></text>
</staticText>
<staticText>
<reportElement x="355" y="0" width="100" height="20" uuid="f19e05c8-f1bf-4d94-927d-07111ed068df"/>
<textElement>
<font isBold="true" isUnderline="true"/>
</textElement>
<text><![CDATA[Status]]></text>
</staticText>
<staticText>
<reportElement x="455" y="0" width="100" height="20" uuid="8a8040c2-e6ba-4473-835f-c9cfe3568fb9"/>
<textElement>
<font isBold="true" isUnderline="true"/>
</textElement>
<text><![CDATA[Last Login]]></text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="22" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="100" height="20" uuid="aec5f07a-b9fb-4ce1-9e7e-957f6315acb0"/>
<textFieldExpression><![CDATA[$F{user_name}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="100" y="0" width="255" height="20" uuid="04eef3a7-87ca-4a27-9392-1368a6ba2fd1"/>
<textFieldExpression><![CDATA[$F{email}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="455" y="0" width="100" height="20" uuid="24a12a8f-a1e1-4ae3-adb7-bbcf450560ee"/>
<textFieldExpression><![CDATA[$F{registered_date}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="355" y="2" width="100" height="20" uuid="47051f05-f634-4c32-97cc-ce9af7b8f382"/>
<textFieldExpression><![CDATA[$F{status}.equals( 1 ) ? "Aktif" : ""]]></textFieldExpression>
</textField>
</band>
</detail>
<columnFooter>
<band height="45" splitType="Stretch"/>
</columnFooter>
<pageFooter>
<band height="54" splitType="Stretch"/>
</pageFooter>
<summary>
<band height="42" splitType="Stretch"/>
</summary>
</jasperReport>
...@@ -135,7 +135,7 @@ def restore_csv(table, filename, get_file_func=get_file, db_session=DBSession): ...@@ -135,7 +135,7 @@ def restore_csv(table, filename, get_file_func=get_file, db_session=DBSession):
# penambahan parameter db_sesion apabila caller mempunyai db_sesion yang berbeda # penambahan parameter db_sesion apabila caller mempunyai db_sesion yang berbeda
# modified by tatang 12-02-2019 # modified by tatang 12-02-2019
# alasan: bila terjadi kesalahan append, # alasan: bila terjadi kesalahan append,
# masih memungkinkan update yg sudah ada dgn syarat is value dari keys masih sama # masih memungkinkan update yg sudah ada dgn syarat is value dari keys masih sama
# sperti salah route url asalkan kode msh sama # sperti salah route url asalkan kode msh sama
def append_csv(table, filename, keys, get_file_func=get_file, def append_csv(table, filename, keys, get_file_func=get_file,
db_session=DBSession, update_exist=False): db_session=DBSession, update_exist=False):
......
*.DS_Store
*.sublime-project
*.sublime-workspace
node_modules/*
*.log
.idea/
{
"debug": true,
"devel": true,
"browser": true,
"asi": true,
"unused": true,
"eqnull": true
}
\ No newline at end of file \ No newline at end of file
language: node_js
node_js:
- 8
before_script:
- npm install -g grunt-cli
before_install: npm install -g npm@latest
install: npm ci
# Contributing
Want to help contribute something to the project? Awesome! :smile:
Please take a moment to review this doc to make contributions easy and effective for everyone.
If there’s anything you’d like to discuss before diving in, you can find us on Gitter.
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/amsul/pickadate.js)
<a name="bugs"></a>
## Bug reports
If you believe you’ve found a bug within the repository code:
- Search the existing issues to avoid duplicates and to check if it has already been solved.
- Make sure you’re using the latest build.
- Isolate the problem and create a [reduced test case](http://css-tricks.com/6263-reduced-test-cases/) - preferably supported with a live example.
- Try to be as detailed as possible in the report (OS, browser, expected outcome vs actual outcome, etc).
- Please **do not** use the issue tracker for personal support requests. Instead try [Stack Overflow](http://stackoverflow.com/questions/tagged/pickadate) or the likes with a `pickadate` tag.
<a name="pull-requests"></a>
## Pull requests
If you’re submitting a pull request, please respect the coding standards used (indentations, comments, semi-colons, etc) as per the **Golden Rule**:
> All code in any code base should look like a single person typed it, no matter how many people contributed.
A few other things to keep in mind:
- Make sure the changes are suitable within the scope of this project.
- Discuss any significant features before endeavoring into developing them. I’d hate to have anyone spend effort on something only for me to not merge it into the main project.
- Include the relevant test coverage if any JavaScript files are involved.
- Compile the project using `grunt build --verbose` to make sure everything passes with a green flag.
- Use the Semantic Versioning guide, as mentioned in the [readme file](https://github.com/amsul/pickadate.js/#readme), in the case that a version bump is due.
#### All pull requests should be submitted to the `master` branch.
<a name="features"></a>
## Feature requests
Feature requests are welcome. But take a moment to find out whether your idea fits within the scope and aims of this project. It’s up to *you* to make a strong case to the merits of this feature. Please provide as much detail and context as possible.
/*!
* This Gruntfile is used to build the project files.
*/
/*jshint
node: true
*/
module.exports = function( grunt ) {
// Read the package manifest.
var packageJSON = grunt.file.readJSON( 'package.json' )
// Load the NPM tasks.
grunt.loadNpmTasks( 'grunt-contrib-watch' )
grunt.loadNpmTasks( 'grunt-contrib-jshint' )
grunt.loadNpmTasks( 'grunt-contrib-qunit' )
grunt.loadNpmTasks( 'grunt-contrib-less' )
grunt.loadNpmTasks( 'grunt-contrib-cssmin' )
grunt.loadNpmTasks( 'grunt-contrib-uglify' )
grunt.loadNpmTasks( 'grunt-autoprefixer' )
// Setup the initial configurations.
grunt.initConfig({
// Add the package data.
pkg: packageJSON,
// Set up the directories.
dirs: {
tests: 'tests',
lib: {
src: 'lib',
min: 'lib/compressed'
},
themes: {
src: 'lib/themes-source',
dest: 'lib/themes',
min: 'lib/compressed/themes'
},
translations: {
src: 'lib/translations',
min: 'lib/compressed/translations'
},
},
// Compile LESS into CSS.
less: {
options: {
style: 'expanded'
},
themes: {
files: {
'<%= dirs.themes.dest %>/default.css': [ '<%= dirs.themes.src %>/base.less', '<%= dirs.themes.src %>/default.less' ],
'<%= dirs.themes.dest %>/classic.css': [ '<%= dirs.themes.src %>/base.less', '<%= dirs.themes.src %>/classic.less' ],
'<%= dirs.themes.dest %>/default.date.css': [ '<%= dirs.themes.src %>/base.date.less', '<%= dirs.themes.src %>/default.date.less' ],
'<%= dirs.themes.dest %>/default.time.css': [ '<%= dirs.themes.src %>/base.time.less', '<%= dirs.themes.src %>/default.time.less' ],
'<%= dirs.themes.dest %>/classic.date.css': [ '<%= dirs.themes.src %>/base.date.less', '<%= dirs.themes.src %>/classic.date.less' ],
'<%= dirs.themes.dest %>/classic.time.css': [ '<%= dirs.themes.src %>/base.time.less', '<%= dirs.themes.src %>/classic.time.less' ],
'<%= dirs.themes.dest %>/rtl.css': [ '<%= dirs.themes.src %>/rtl.less' ]
}
}
},
// Lint the files.
jshint: {
options: {
jshintrc: true
},
gruntfile: 'Gruntfile.js',
lib: [
'<%= dirs.tests %>/units/*.js',
'<%= dirs.lib.src %>/**/*.js',
// Ignore the legacy and minified files.
'!<%= dirs.lib.src %>/legacy.js',
'!<%= dirs.lib.src %>/compressed/**/*.js'
]
},
// Minify all the things!
uglify: {
options: {
preserveComments: 'some'
},
lib: {
files: [
{
expand : true,
cwd : '<%= dirs.lib.src %>',
src : [ '**/*.js', '!compressed/**/*.js' ],
dest : '<%= dirs.lib.min %>'
}
]
}
},
cssmin: {
lib: {
expand: true,
cwd: '<%= dirs.themes.dest %>',
src: [ '**/*.css', '!compressed/**/*.css' ],
dest: '<%= dirs.themes.min %>'
}
},
// Prefix the styles.
autoprefixer: {
options: {
browsers: [ '> 5%', 'last 2 versions', 'ie 8', 'ie 9' ]
},
themes: {
src: '<%= dirs.themes.dest %>/**/*.css'
},
},
// Unit test the files.
qunit: {
lib: [ '<%= dirs.tests %>/units/all.htm' ]
},
// Watch the project files.
watch: {
develop: {
files: [
'<%= dirs.themes.src %>/**/*.less'
],
tasks: [ 'develop-once' ]
},
}
}) //grunt.initConfig
// Register the tasks.
grunt.registerTask( 'default', [ 'develop' ] )
grunt.registerTask( 'develop', [ 'develop-once', 'watch:develop' ] )
grunt.registerTask( 'develop-once', [ 'less:themes', 'autoprefixer:themes' ] )
grunt.registerTask( 'package', [ 'develop-once', 'uglify', 'cssmin' ] )
grunt.registerTask( 'test', [ 'jshint', 'qunit' ] )
} //module.exports
Copyright 2014 Amsul, http://amsul.ca
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file \ No newline at end of file
# pickadate [![Build status: master](https://travis-ci.org/amsul/pickadate.js.svg?branch=master)](https://travis-ci.org/amsul/pickadate.js) [![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/pickadate/badge?style=rounded)](https://www.jsdelivr.com/package/npm/pickadate)
The mobile-friendly, responsive, and lightweight jQuery date & time input picker.
[![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/pickadate)
#### To get started, check out the:
[Homepage](http://amsul.ca/pickadate.js) - [Date picker](http://amsul.ca/pickadate.js/date) - [Time picker](http://amsul.ca/pickadate.js/time) - [API](http://amsul.ca/pickadate.js/api)
#### To get it:
[Download the latest stable build](https://github.com/amsul/pickadate.js/archive/master.zip)
*or*
`git clone git://github.com/amsul/pickadate.js.git`
*or*
`bower install pickadate`
<br>
## Library files
The `lib` folder includes the library files with a `compressed` folder containing the minified counter-parts. These files are minified using [Grunt](#building-with-grunt).
### Pickers
There are three picker files:
* `picker.js` The core file (required before any other picker)
* `picker.date.js` The date picker
* `picker.time.js` The time picker
_To support old browsers, namely IE8, **also include** the `legacy.js` file._
### Themes
All themes are [generated using LESS](#less-styling) and compiled from the `lib/themes-source` folder into the `lib/themes` folder.
There are two themes:
* `default.css` The default modal-style theme
* `classic.css` The classic dropdown-style theme
Based on the theme, pick the relevant picker styles:
* `default.date.css` and `default.time.css` when using the default theme
* `classic.date.css` and `classic.time.css` when using the classic theme
__**__ For languages with text flowing from right-to-left, also include the `rtl.css` stylesheet.
### Translations
The translations live in the `lib/translations` folder. There are currently [43 language translations](https://github.com/amsul/pickadate.js/tree/master/lib/translations) included.
<br>
## Building with Grunt
[Grunt](http://gruntjs.com/) `~0.4.5` is used to build the project files. To get started, clone the project and then run:
- `npm install` to get the required node modules.
- `grunt test --verbose` to confirm you have all the dependencies.
Type out `grunt --help` to see a list of all the tasks available. The generally used tasks are:
- `grunt develop` compiles the LESS files and watches for any source changes.
- `grunt package` compiles and then minifies the source files.
- `grunt test` tests the entire package.
<br>
<a name="less-styling"></a>
## Styling with LESS
The picker themes are built using [LESS](http://lesscss.org/) with Grunt. To customize the CSS output, read the `_variables.less` file in the `lib/themes-source` folder. You can specify:
- colors for the theme,
- sizes for the picker,
- media-query breakpoints,
- and a whole bunch of other stuff.
Make sure to run the `grunt develop` task before making any changes to compile it into CSS.
<br>
## Bugs
Before opening a new issue, please search the existing [Issues](https://github.com/amsul/pickadate.js/issues) for anything similar – there might already be an answer to your problem. You might also wanna check out the [Contributing](https://github.com/amsul/pickadate.js/blob/master/CONTRIBUTING.md) guide.
<br>
## Contributing
Before contributing any code to the project, please take a look at the [Contributing](https://github.com/amsul/pickadate.js/blob/master/CONTRIBUTING.md) guide.
If there’s anything you’d like to discuss, we like to hang out on Spectrum.
[![Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/pickadate)
<br>
## Support
If you find this library useful and would like to see further development, consider [supporting it](http://selz.co/1g80kCZ).
<br><br>
---
© 2014 [Amsul](http://twitter.com/amsul_)
Licensed under [MIT](http://amsul.ca/MIT)
{
"name": "pickadate",
"description": "The mobile-friendly, responsive, and lightweight jQuery date & time input picker.",
"main": [
"lib/picker.js",
"lib/picker.date.js",
"lib/picker.time.js",
"lib/themes/default.css",
"lib/themes/default.date.css",
"lib/themes/default.time.css"
],
"license": "MIT",
"ignore": [
"*.md",
"*.htm",
"_docs",
"demo"
],
"keywords": [
"date",
"time",
"picker",
"input",
"responsive"
],
"authors": {
"name": "Amsul",
"email": "reach@amsul.ca",
"homepage": "http://amsul.ca"
},
"homepage": "http://amsul.ca/pickadate.js",
"repository": {
"type": "git",
"url": "git://github.com/amsul/pickadate.js.git"
},
"dependencies": {
"jquery": ">=1.7"
},
"devDependencies": {
"grunt": "^0.4.5",
"grunt-autoprefixer": "^1.0.1",
"grunt-contrib-copy": "^0.5.0",
"grunt-contrib-cssmin": "^0.9.0",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-less": "^0.11.4",
"grunt-contrib-qunit": "^0.4.0",
"grunt-contrib-uglify": "^0.4.1",
"grunt-contrib-watch": "^0.6.1",
"phantomjs": "^1.9.7-5",
"zlib-browserify": "0.0.3"
}
}
\ No newline at end of file \ No newline at end of file
{
"name": "pickadate",
"version": "3.6.4",
"title": "pickadate.js",
"description": "The mobile-friendly, responsive, and lightweight jQuery date & time input picker.",
"keywords": [
"date",
"time",
"picker",
"input",
"responsive"
],
"homepage": "http://amsul.ca/pickadate.js",
"bugs": "https://github.com/amsul/pickadate.js/issues",
"license": "MIT",
"author": {
"name": "Amsul",
"email": "reach@amsul.ca",
"url": "http://amsul.ca"
},
"files": [
"lib",
"tests",
"README.md",
"Gruntfile.js"
],
"repository": {
"type": "git",
"url": "https://github.com/amsul/pickadate.js.git"
},
"scripts": {
"prebump": "npm test",
"bump": "node ./version-bump.js",
"postbump": "npx grunt package && node ./version-commit.js",
"push": "git push && git push origin --tags && npm publish",
"test": "npx grunt test --verbose"
},
"dependencies": {
"jquery": ">=1.7"
},
"devDependencies": {
"commander": "^2.8.0",
"glob": "^5.0.5",
"grunt": "^0.4.5",
"grunt-autoprefixer": "^3.0.0",
"grunt-contrib-copy": "^0.8.0",
"grunt-contrib-cssmin": "^0.12.2",
"grunt-contrib-jshint": "^0.11.2",
"grunt-contrib-less": "^1.0.1",
"grunt-contrib-qunit": "^2.0.0",
"grunt-contrib-uglify": "^0.9.1",
"grunt-contrib-watch": "^0.6.1",
"qunitjs": "1.x",
"semver": "^4.3.3",
"shelljs": "^0.4.0",
"zlib-browserify": "0.0.3"
}
}
\ No newline at end of file \ No newline at end of file
<!doctype html>
<html>
<meta charset="utf-8">
<meta name="author" content="Amsul - http://amsul.ca">
<meta name="viewport" content="width=device-width,user-scalable=no">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Pickadate.js</title>
<link rel="stylesheet" href="../../lib/themes/default.css">
<link rel="stylesheet" href="../../lib/themes/default.date.css">
<!--[if lt IE 9]>
<script>document.createElement('section')</script>
<style type="text/css">
.holder {
position: relative;
z-index: 10000;
}
.datepicker {
display: block;
}
</style>
<![endif]-->
<body>
<section class="section">
<form>
<fieldset>
<h3><label for="input_01">Pick a date. Go ahead...</label></h3>
<input
id="input_01"
class="datepicker"
name="date"
type="text"
autofocus
value="14 August, 2014"
data-value="2014-08-08">
<br><br><br><br><br>
<!-- <button type="button">Disable all dates</button>
<input class="button" type="submit" value="open"> -->
</fieldset>
</form>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<div id="container"></div>
</section>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="../../lib/picker.js"></script>
<script src="../../lib/picker.date.js"></script>
<script src="../../lib/legacy.js"></script>
<script type="text/javascript">
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();
if(dd<10) {
dd='0'+dd;
}
if(mm<10) {
mm='0'+mm;
}
today = dd+'/'+mm+'/'+yyyy;
var $input = $( '.datepicker' ).pickadate({
formatSubmit: 'yyyy/mm/dd',
// min: [2015, 7, 14],
container: '#container',
// editable: true,
closeOnSelect: false,
closeOnClear: false,
})
var picker = $input.pickadate('picker')
// picker.set('select', '14 October, 2014')
// picker.open()
// $('button').on('click', function() {
// picker.set('disable', true);
// });
</script>
</body>
</html>
<!doctype html>
<html>
<meta charset="utf-8">
<meta name="author" content="Amsul - http://amsul.ca">
<meta name="viewport" content="width=device-width">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Pickadate.js</title>
<link rel="stylesheet" href="../../lib/themes/default.css">
<link rel="stylesheet" href="../../lib/themes/default.time.css">
<!--[if lt IE 9]>
<script>document.createElement('section')</script>
<style type="text/css">
.holder {
position: relative;
z-index: 10000;
}
.datepicker {
display: block;
}
</style>
<![endif]-->
<body>
<section class="section">
<form>
<fieldset>
<h3><label for="input_01">Pick a time. Go ahead...</label></h3>
<input
id="input_from"
class="datepicker"
type="time"
name="time"
autofocus>
<!-- valuee="2:30 AM"
data-value="0:00" -->
</fieldset>
</form>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="../../lib/picker.js"></script>
<script src="../../lib/picker.time.js"></script>
<script src="../../lib/legacy.js"></script>
<script type="text/javascript">
var $input = $( '.datepicker' ).pickatime({
})
var picker = $input.pickatime('picker')
picker.open()
</script>
</body>
</html>
<!doctype html>
<meta charset="utf-8">
<title>pickadate.js &#8226; QUnit testing</title>
<link rel="stylesheet" href="../../node_modules/qunitjs/qunit/qunit.css">
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="../../lib/picker.js"></script>
<script src="../../lib/picker.date.js"></script>
<script src="../../lib/picker.time.js"></script>
<script src="../../node_modules/qunitjs/qunit/qunit.js"></script>
<script src="base.js"></script>
<script src="date.js"></script>
<script src="time.js"></script>
</body>
\ No newline at end of file \ No newline at end of file
/*jshint node: true*/
var program = require('commander')
var semver = require('semver')
var grunt = require('grunt')
var glob = require('glob').sync
program
.option('-p, --patch', 'set the version as the next patch')
.option('-m, --minor', 'set the version as the next minor')
.option('-M, --major', 'set the version as the next major')
.parse(process.argv)
if (program.patch) {
bumpVersion('patch')
return
}
if (program.minor) {
bumpVersion('minor')
return
}
if (program.major) {
bumpVersion('major')
return
}
grunt.fail.fatal('No release type specified')
return
function bumpVersion(release) {
grunt.log.writeln('Bumping package version by a ' + release)
var version = readPackageVersion()
grunt.log.writeln('Current package version: ' + version)
version = semver.inc(version, release)
grunt.log.writeln('Updated package version: ' + version)
writePackageVersion(version)
grunt.log.writeln('Done updating the package version')
updateLibraryFiles(version)
grunt.log.writeln('Done updating the library files')
}
function readPackageVersion() {
var pkg = require('./package')
return pkg.version
}
function writePackageVersion(version) {
var pkg = require('./package')
pkg.version = version
grunt.file.write('./package.json', JSON.stringify(pkg, null, ' '))
}
function updateLibraryFiles(version) {
var versionRegex = /^(\s*\/\*![^\/]+?v)(\d+\.\d+\.\d+)(([^\n]+?)(\d+\/\d+\/\d+))?/
var today = grunt.template.today('yyyy/mm/dd')
var files = glob('lib/*.js')
files.forEach(updateLibraryFile)
function updateLibraryFile(filePath) {
var content = grunt.file.read(filePath)
if (versionRegex.test(content)) {
content = content.split(versionRegex)
content = content[1] + version + (content[4] || '') + (content[5] ? today : '') + (content[6] || '')
}
grunt.file.write(filePath, content)
}
}
\ No newline at end of file \ No newline at end of file
/*jshint node: true*/
var grunt = require('grunt')
var exec = require('shelljs').exec
var pkg = require('./package')
var isSuccessful = commitAndTag(pkg.version)
if (!isSuccessful) {
grunt.fail.fatal('Unable to commit and tag version')
}
return
function commitAndTag(version) {
var code = exec([
'git add .',
'git commit -m "Release v' + version + '"',
'git tag ' + version,
].join(' && ')).code
return !code
}
\ No newline at end of file \ No newline at end of file
...@@ -477,7 +477,7 @@ div.col-md-6 { ...@@ -477,7 +477,7 @@ div.col-md-6 {
padding: 7px !important; padding: 7px !important;
} }
.form-horizontal .checkbox, .form-horizontal .radio { .form-horizontal .checkbox, .form-horizontal .radio, .form-horizontal .radio-inline{
padding: 0px; padding: 0px;
} }
...@@ -515,7 +515,7 @@ div.col-md-6 { ...@@ -515,7 +515,7 @@ div.col-md-6 {
} }
.checkbox label, .radio label { .checkbox label, .radio label, .radio-inline {
font-size: 10px !important; font-size: 10px !important;
} }
......
...@@ -32,6 +32,16 @@ $(document).ready(function () { ...@@ -32,6 +32,16 @@ $(document).ready(function () {
*/ */
}); });
jQuery.browser = {};
(function () {
jQuery.browser.msie = false;
jQuery.browser.version = 0;
if (navigator.userAgent.match(/MSIE ([0-9]+)\./)) {
jQuery.browser.msie = true;
jQuery.browser.version = RegExp.$1;
}
})();
function number_format(number, decimals, dec_point, thousands_sep) { function number_format(number, decimals, dec_point, thousands_sep) {
// Strip all characters but numerical ones. // Strip all characters but numerical ones.
number = (number + '').replace(/[^0-9+\-Ee.]/g, ''); number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
......
from pyreportjasper import PyReportJasper
from opensipkd.base.tools import get_random_string
from opensipkd.base import get_settings, get_params
from platform import python_version
import os
from opensipkd.tools.report import * from opensipkd.tools.report import *
from opensipkd.base import log from opensipkd.base import log
log.warning("Opensipkd.base.tools.pbb depreciated use opensipkd.tools.pbb") log.warning("Opensipkd.base.tools.pbb depreciated use opensipkd.tools.pbb")
# -*- coding: utf-8 -*-
db_driver_port = {
"postgresql": ["postgres", "5432", "org.postgresql.Driver", "jdbc:postgresql://localhost:5432/pjdl_ciamis"],
"oracle": ["oracle", "1512", "oracle.jdbc.driver.OracleDriver"],
}
def jasper_compile(input_file):
# REPORTS_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'reports')
# input_file = os.path.join(input_file)
# file_ext = os.path.splitext(input_file)
# output_file = os.path.join(REPORTS_DIR, 'csv')
pyreportjasper = PyReportJasper()
pyreportjasper.compile(write_jasper=True)
def jasper_export(input_file, output_file=None, schema=None,
output_formats=["pdf"], dburl="sqlalchemy.url",
parameters={}, db_schema=None):
db = get_params(dburl).split("@")
db_driver, db_user, db_password = db[0].split(':')
db_servers, db_name = db[1].split('/')
# db_user, db_password = db_users.split(":")
if db_servers.find(':') > 1:
db_host, db_port = db_servers.split(":")
else:
db_host = db_servers
db_port = db_driver_port[db_driver][1]
# db_host = db_server
jdbc_dir = get_params("jdbc_dir", "")
# if not jdbc_dir:
# java_home = os.getenv("JAVA_HOME")
# jdbc_dir = os.path.join(java_home, 'lib', db_driver_port[db_driver][2])
jdbc_driver = db_driver_port[db_driver][2]
db_driver = db_driver_port[db_driver][0]
log.info(jdbc_dir)
input_file = input_file.split(":")
if len(input_file) > 1:
path = __import__(input_file[0])
path = os.path.dirname(path.__file__)
input_file = os.path.join(path, input_file[1])
else:
input_file=input_file[0]
if not output_file:
output_file = get_params("tmp_report", "/tmp")
output_file = os.path.join(output_file, get_random_string(32))
conn = {
'driver': db_driver,
'username': db_user.strip('/'),
'password': db_password,
'host': db_host,
'database': db_name,
'schema': db_schema,
'port': db_port,
'jdbc_dir': jdbc_dir,
'jdbc_driver': jdbc_driver,
}
pyreportjasper = PyReportJasper()
# log.info(input_file)
# log.info(output_file)
# log.info(conn)
# log.info(output_formats)
parameters.update({'python_version': python_version()})
pyreportjasper.config(
input_file,
output_file,
db_connection=conn,
output_formats=output_formats,
parameters=parameters,
locale='en_US'
)
# pyreportjasper.compile(write_jasper=True)
pyreportjasper.process_report()
output_files = [".".join([output_file, f]) for f in output_formats]
log.info(output_files)
return output_files
...@@ -15,7 +15,7 @@ from pyramid.response import Response ...@@ -15,7 +15,7 @@ from pyramid.response import Response
from pyramid.security import remember from pyramid.security import remember
from pyramid.view import view_config from pyramid.view import view_config
from opensipkd.base import get_params from opensipkd.base import get_params, get_urls
from opensipkd.base.tools.api import rpc_auth from opensipkd.base.tools.api import rpc_auth
from .base_views import BaseView from .base_views import BaseView
...@@ -68,11 +68,11 @@ class Home(BaseView): ...@@ -68,11 +68,11 @@ class Home(BaseView):
log.info(request.session.peek_flash()) log.info(request.session.peek_flash())
if modules_default: if modules_default:
if request.user and request.has_permission(modules_default): if request.user and request.has_permission(modules_default):
return HTTPFound(location=request.route_url(modules_default)) return HTTPFound(location=get_urls(request.route_url(modules_default)))
elif request.user and len(request.session.peek_flash('error')) < 2: elif request.user and len(request.session.peek_flash('error')) < 2:
return HTTPFound(location=request.route_url(modules_default)) return HTTPFound(location=get_urls(request.route_url(modules_default)))
elif not request.user: elif not request.user:
return HTTPFound(location=request.route_url(modules_default)) return HTTPFound(location=get_urls(request.route_url(modules_default)))
logo = get_params('logo', "static/img/logo.png") logo = get_params('logo', "static/img/logo.png")
home_tpl = get_params("home_tpl") home_tpl = get_params("home_tpl")
if home_tpl: if home_tpl:
...@@ -87,7 +87,7 @@ class Home(BaseView): ...@@ -87,7 +87,7 @@ class Home(BaseView):
@view_config(context=HTTPForbidden, renderer='templates/403.pt') @view_config(context=HTTPForbidden, renderer='templates/403.pt')
def http_forbidden(request): def http_forbidden(request):
if not request.is_authenticated: if not request.is_authenticated:
next_url = request.route_url('login', _query={'next': request.url}) next_url = get_urls(request.route_url('login', _query={'next': request.url}))
return HTTPSeeOther(location=next_url) return HTTPSeeOther(location=next_url)
request.response.status = 403 request.response.status = 403
...@@ -125,7 +125,7 @@ def view_password(request): ...@@ -125,7 +125,7 @@ def view_password(request):
if not request.POST: if not request.POST:
return dict(form=form.render()) return dict(form=form.render())
if 'save' not in request.POST: if 'save' not in request.POST:
return HTTPFound(location=request.route_url('home')) return HTTPFound(location=request._host)
schema.request = request schema.request = request
controls = request.POST.items() controls = request.POST.items()
try: try:
...@@ -135,7 +135,7 @@ def view_password(request): ...@@ -135,7 +135,7 @@ def view_password(request):
UserService.set_password(request.user, c['new_password']) UserService.set_password(request.user, c['new_password'])
DBSession.add(request.user) DBSession.add(request.user)
request.session.flash('Password baru Anda sudah disimpan.') request.session.flash('Password baru Anda sudah disimpan.')
return HTTPFound(location=request.route_url('home')) return HTTPFound(location=request._host)
###################################### ######################################
......
...@@ -13,7 +13,7 @@ from sqlalchemy.orm import aliased ...@@ -13,7 +13,7 @@ from sqlalchemy.orm import aliased
from .company import company_widget from .company import company_widget
from .upload import AddSchema as UploadSchema from .upload import AddSchema as UploadSchema
from opensipkd.models import DBSession, Departemen, Partner, PartnerDepartemen from opensipkd.models import DBSession, Departemen, Partner, PartnerDepartemen
from ..views import ColumnDT, DataTables, BaseView from ..views import ColumnDT, DataTables, BaseView, get_urls
SESS_ADD_FAILED = 'Tambah departemen gagal' SESS_ADD_FAILED = 'Tambah departemen gagal'
SESS_EDIT_FAILED = 'Edit departemen gagal' SESS_EDIT_FAILED = 'Edit departemen gagal'
...@@ -87,7 +87,7 @@ class AddSchema(colander.Schema): ...@@ -87,7 +87,7 @@ class AddSchema(colander.Schema):
size=60, min_length=3, size=60, min_length=3,
requirements=(("typeahead", None), ("deform", None), requirements=(("typeahead", None), ("deform", None),
{"js": "opensipkd.base:static/js/form/departemen.js"}), {"js": "opensipkd.base:static/js/form/departemen.js"}),
values=f"{request.route_url('departemen')}/hon/act") values=get_urls(f"{request.route_url('departemen')}/hon/act"))
if request.user.company_id: if request.user.company_id:
self["company_id"].widget = widget.HiddenWidget() self["company_id"].widget = widget.HiddenWidget()
self["company_id"].default = request.user.company_id self["company_id"].default = request.user.company_id
......
...@@ -7,7 +7,7 @@ from pyramid.view import (view_config, ) ...@@ -7,7 +7,7 @@ from pyramid.view import (view_config, )
from sqlalchemy.orm import aliased from sqlalchemy.orm import aliased
from ..views import ColumnDT, DataTables, BaseView from ..views import ColumnDT, DataTables, BaseView
from .. import get_urls
_ = TranslationStringFactory("opensipkd") _ = TranslationStringFactory("opensipkd")
SESS_ADD_FAILED = 'Tambah menu gagal' SESS_ADD_FAILED = 'Tambah menu gagal'
......
...@@ -7,6 +7,7 @@ from opensipkd.base.views.kecamatan import kecamatan_widget ...@@ -7,6 +7,7 @@ from opensipkd.base.views.kecamatan import kecamatan_widget
from opensipkd.base.views.provinsi import provinsi_widget from opensipkd.base.views.provinsi import provinsi_widget
from opensipkd.tools import mem_tmp_store from opensipkd.tools import mem_tmp_store
from .. import get_urls
class NamaSchema(colander.Schema): class NamaSchema(colander.Schema):
...@@ -132,8 +133,7 @@ class PartnerSchema(NamaSchema): ...@@ -132,8 +133,7 @@ class PartnerSchema(NamaSchema):
def after_bind(self, schema, kwargs): def after_bind(self, schema, kwargs):
request = kwargs["request"] request = kwargs["request"]
prefix = request.route_url("home") prefix = get_urls(request.route_url("home"))
self["provinsi_id"].slave_url=f"{prefix}/dati2/select/act?provinsi_id=" self["provinsi_id"].slave_url = f"{prefix}/dati2/select/act?provinsi_id="
self["dati2_id"].slave_url=f"{prefix}/kecamatan/select/act?dati2_id=" self["dati2_id"].slave_url = f"{prefix}/kecamatan/select/act?dati2_id="
self["kecamatan_id"].slave_url = f"{prefix}/desa/select/act?kecamatan_id=" self["kecamatan_id"].slave_url = f"{prefix}/desa/select/act?kecamatan_id="
...@@ -47,6 +47,7 @@ from . import widget_os ...@@ -47,6 +47,7 @@ from . import widget_os
from .base_views import need_captcha, get_url_captcha from .base_views import need_captcha, get_url_captcha
from .user_login import regenerate_security_code, send_email_security_code from .user_login import regenerate_security_code, send_email_security_code
from ..views import BaseView from ..views import BaseView
from .. import get_urls
_ = TranslationStringFactory('user') _ = TranslationStringFactory('user')
...@@ -146,7 +147,7 @@ def _show_error(request, msg): ...@@ -146,7 +147,7 @@ def _show_error(request, msg):
def show_error(request, msg): def show_error(request, msg):
_show_error(request, msg) _show_error(request, msg)
return HTTPFound(location=request.route_url('home')) return HTTPFound(location=get_urls(request.route_url('home')))
# def reg_buttons(): # def reg_buttons():
...@@ -310,16 +311,16 @@ class Registrasi(BaseView): ...@@ -310,16 +311,16 @@ class Registrasi(BaseView):
def view_register(self): def view_register(self):
if "g_state" in self.req.cookies: if "g_state" in self.req.cookies:
if "id_info" not in self.ses or not self.ses["id_info"]: if "id_info" not in self.ses or not self.ses["id_info"]:
return HTTPFound(location=self.req.route_url("login")) return HTTPFound(location=get_urls(self.req.route_url("login")))
request = self.req request = self.req
reg_form = get_params("reg_form") reg_form = get_params("reg_form")
if reg_form: if reg_form:
return HTTPFound(location=self.req.route_url(reg_form)) return HTTPFound(location=get_urls(self.req.route_url(reg_form)))
self.bindings = dict(user=None) self.bindings = dict(user=None)
if request.user: if request.user:
return HTTPFound(location=request.route_url("profile")) return HTTPFound(location=get_urls(request.route_url("profile")))
return super(Registrasi, self).view_add() return super(Registrasi, self).view_add()
...@@ -365,7 +366,7 @@ class Registrasi(BaseView): ...@@ -365,7 +366,7 @@ class Registrasi(BaseView):
self.buttons = (btn_save, btn_cancel) self.buttons = (btn_save, btn_cancel)
reg_form = get_params("reg_form") reg_form = get_params("reg_form")
if reg_form: if reg_form:
return HTTPFound(location=self.req.route_url(reg_form)) return HTTPFound(location=get_urls(self.req.route_url(reg_form)))
self.bindings = dict(user=self.req.user) self.bindings = dict(user=self.req.user)
resp = super(Registrasi, self).view_edit() resp = super(Registrasi, self).view_edit()
if not resp: if not resp:
......
<html tal:define="home request.route_url('home')[:-1];"> <html tal:define="home request._host;">
<body> <body>
<div class="well"> <div class="well">
<h3>Forbidden</h3> <h3>Forbidden</h3>
......
<html tal:define="home request.route_url('home')[:-1];"> <html tal:define="home request._host;">
<body> <body>
<div class="well"> <div class="well">
<h2>${request.app_name}</h2> <h2>${request.app_name}</h2>
......
<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>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" tal:define="home request.route_url('home');"> <html lang="en" tal:define="home request._host;">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content=""> <meta name="author" content="">
<link rel="shortcut icon" href="${home}static/img/favicon.png"> <link rel="shortcut icon" href="${home}/static/img/favicon.png">
<title tal:content="request.title" /> <title tal:content="request.title" />
<!-- SmartAdmin Styles : Caution! DO NOT change the order --> <!-- SmartAdmin Styles : Caution! DO NOT change the order -->
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/smartadmin-production-plugins.min.css"> <link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/smartadmin-production-plugins.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/smartadmin-production.min.css"> <link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/smartadmin-production.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/smartadmin-skins.min.css"> <link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/smartadmin-skins.min.css">
<!-- Bootstrap core CSS --> <!-- Bootstrap core CSS -->
<link href="${home}static/v3/css/bootstrap.min.css" rel="stylesheet"> <link href="${home}/static/v3/css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome --> <!-- Font Awesome -->
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/font-awesome.min.css"> <link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/font-awesome.min.css">
<!-- Jquery CSS --> <!-- Jquery CSS -->
<link href="${home}static/v3/plugin/jqueryui/themes/base/jquery-ui.min.css" rel="stylesheet"> <link href="${home}/static/v3/plugin/jqueryui/themes/base/jquery-ui.min.css" rel="stylesheet">
<!-- DataTables --> <!-- DataTables -->
<link href="${home}static/v3/plugin/datatables/1.10/media/css/dataTables.bootstrap.css" rel="stylesheet"> <link href="${home}/static/v3/plugin/datatables/1.10/media/css/dataTables.bootstrap.css" rel="stylesheet">
<link href="${home}deform_static/css/form.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}/deform_static/css/typeahead.css" rel="stylesheet">
<link href="${home}static/css/theme.css" rel="stylesheet"> <link href="${home}/static/css/theme.css" rel="stylesheet">
<link href="${home}static/css/navbar-fixed-top.css" rel="stylesheet"> <link href="${home}/static/css/navbar-fixed-top.css" rel="stylesheet">
<!-- Home CSS --> <!-- Home CSS -->
<link href="${home}static/css/custom.css" rel="stylesheet" type="text/css"> <link href="${home}/static/css/custom.css" rel="stylesheet" type="text/css">
<metal:css define-slot="css_files"></metal:css> <metal:css define-slot="css_files"></metal:css>
<style> <style>
#content { #content {
...@@ -58,12 +58,12 @@ ...@@ -58,12 +58,12 @@
<!-- <div class="navbar-collapse collapse" tal.condition="not request.user"> --> <!-- <div class="navbar-collapse collapse" tal.condition="not request.user"> -->
<!-- <ul class="nav navbar-nav"> --> <!-- <ul class="nav navbar-nav"> -->
<!-- <li><a href="${home}eis/sipkd" class="navbar-brand txt-color-white"><strong>${request.company}</strong></a></li> --> <!-- <li><a href="${home}/eis/sipkd" class="navbar-brand txt-color-white"><strong>${request.company}</strong></a></li> -->
<!-- </ul> --> <!-- </ul> -->
<!-- <ul class="nav navbar-nav navbar-right" style="margin-right:0px;"> --> <!-- <ul class="nav navbar-nav navbar-right" style="margin-right:0px;"> -->
<!-- <li class="dropdown"> --> <!-- <li class="dropdown"> -->
<!-- <a href="${home}login" class="button txt-color-white"><i class="fa fa-user"></i> Masuk</a> --> <!-- <a href="${home}/login" class="button txt-color-white"><i class="fa fa-user"></i> Masuk</a> -->
<!-- </li> --> <!-- </li> -->
<!-- </ul> --> <!-- </ul> -->
<!-- </div> --> <!-- </div> -->
...@@ -81,21 +81,21 @@ ...@@ -81,21 +81,21 @@
<a href="#" class="dropdown-toggle txt-color-white" data-toggle="dropdown">Admin <b class="caret"></b></a> <a href="#" class="dropdown-toggle txt-color-white" data-toggle="dropdown">Admin <b class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"> <li tal:condition="has_permission(request, ['user-view', 'user-edit'])">
<a href="${home}user">User</a> <a href="${home}/user">User</a>
</li> </li>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])"> <li tal:condition="has_permission(request, ['user-view', 'user-edit'])">
<a href="${home}group">Group</a> <a href="${home}/group">Group</a>
</li> </li>
<li tal:condition="has_permission(request, 'routes')"><a href="${home}routes">Routes</a></li> <li tal:condition="has_permission(request, 'routes')"><a href="${home}/routes">Routes</a></li>
<li tal:condition="has_permission(request, 'upload-logo')"><a href="${home}upload/logo">Upload Logo</a></li> <li tal:condition="has_permission(request, 'upload-logo')"><a href="${home}/upload/logo">Upload Logo</a></li>
<li tal:condition="has_permission(request, 'parameter')"> <li tal:condition="has_permission(request, 'parameter')">
<a href="${home}parameter">Parameter</a></li> <a href="${home}/parameter">Parameter</a></li>
<li tal:condition="has_permission(request, 'departemen')"> <li tal:condition="has_permission(request, 'departemen')">
<a href="${home}departemen">Departemen</a></li> <a href="${home}/departemen">Departemen</a></li>
<li tal:condition="has_permission(request, 'partner')"> <li tal:condition="has_permission(request, 'partner')">
<a href="${home}partner">Partner</a></li> <a href="${home}/partner">Partner</a></li>
<li tal:condition="has_permission(request, 'parameter')"> <li tal:condition="has_permission(request, 'parameter')">
<a href="${home}parameter">Parameter</a></li> <a href="${home}/parameter">Parameter</a></li>
</ul> </ul>
</li> </li>
...@@ -104,15 +104,15 @@ ...@@ -104,15 +104,15 @@
['/password', '/recreate-api-key'] and 'active'"> ['/password', '/recreate-api-key'] and 'active'">
<a href="#" class="dropdown-toggle txt-color-white" data-toggle="dropdown">My Account <b class="caret"></b></a> <a href="#" class="dropdown-toggle txt-color-white" data-toggle="dropdown">My Account <b class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a style="text-transform:capitalize" href="${home}logout">${request.user.nice_username()} Logout</a></li> <li><a style="text-transform:capitalize" href="${home}/logout">${request.user.nice_username()} Logout</a></li>
<li><a style="text-transform:capitalize" href="${home}profile">Profile</a></li> <li><a style="text-transform:capitalize" href="${home}/profile">Profile</a></li>
<li><a style="text-transform:capitalize" href="${home}password">Ubah password</a></li> <li><a style="text-transform:capitalize" href="${home}/password">Ubah password</a></li>
<li tal:condition="request.user.api_key"> <li tal:condition="request.user.api_key">
<a style="text-transform:capitalize" href="${home}recreate-api-key"> <a style="text-transform:capitalize" href="${home}/recreate-api-key">
API Key API Key
</a> </a>
</li> </li>
<li tal:condition="'core' in request.modules and change_unit(request)"><a style="text-transform:capitalize" href="${home}departemen/chg">Ubah Organisasi</a></li> <li tal:condition="'core' in request.modules and change_unit(request)"><a style="text-transform:capitalize" href="${home}/departemen/chg">Ubah Organisasi</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
...@@ -140,20 +140,20 @@ ...@@ -140,20 +140,20 @@
<!-- Bootstrap core JavaScript <!-- Bootstrap core JavaScript
================================================== --> ================================================== -->
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="${home}static/v3/js/jquery-2.1.1.min.js"></script> <script type="text/javascript" src="${home}/static/v3/js/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="${home}static/v3/js/jquery-ui-1.10.3.min.js"></script> <script type="text/javascript" src="${home}/static/v3/js/jquery-ui-1.10.3.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
// Change JQueryUI plugin names to fix name collision with Bootstrap. // Change JQueryUI plugin names to fix name collision with Bootstrap.
$.widget.bridge('uitooltip', $.ui.tooltip); $.widget.bridge('uitooltip', $.ui.tooltip);
$.widget.bridge('uibutton', $.ui.button); $.widget.bridge('uibutton', $.ui.button);
</script> </script>
<script type="text/javascript" src="${home}static/v3/js/bootstrap/bootstrap.min.js"></script> <script type="text/javascript" src="${home}/static/v3/js/bootstrap/bootstrap.min.js"></script>
<script type="text/javascript" src="${home}static/v3/plugin/datatables/1.10/media/js/jquery.dataTables.min.js"></script> <script type="text/javascript" src="${home}/static/v3/plugin/datatables/1.10/media/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="${home}static/v3/plugin/datatables/1.10/media/js/dataTables.bootstrap.js"></script> <script type="text/javascript" src="${home}/static/v3/plugin/datatables/1.10/media/js/dataTables.bootstrap.js"></script>
<script type="text/javascript" src="${home}static/v3/plugin/datatables/1.10/media/js/jquery.dataTables.ext.js"></script> <script type="text/javascript" src="${home}/static/v3/plugin/datatables/1.10/media/js/jquery.dataTables.ext.js"></script>
<script type="text/javascript" src="${home}deform_static/scripts/deform.js"></script> <script type="text/javascript" src="${home}/deform_static/scripts/deform.js"></script>
<script type="text/javascript" src="${home}deform_static/scripts/typeahead.min.js"></script> <script type="text/javascript" src="${home}/deform_static/scripts/typeahead.min.js"></script>
<script type="text/javascript" src="${home}static/js/tools.js"></script> <script type="text/javascript" src="${home}/static/js/tools.js"></script>
<metal:js define-slot="js_files"></metal:js> <metal:js define-slot="js_files"></metal:js>
<script metal:define-slot="scripts"></script> <script metal:define-slot="scripts"></script>
......
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en-us" <html lang="en-us"
tal:define=" tal:define="
home request.route_url('home')[:-1]; home request._host;
user_path ['user', 'user-add', 'user-edit', 'user-view', 'user-delete']; user_path ['user', 'user-add', 'user-edit', 'user-view', 'user-delete'];
user_ext_path ['user-ext', 'user-ext-view', 'user-ext-delete']; user_ext_path ['user-ext', 'user-ext-view', 'user-ext-delete'];
group_path ['group', 'group-add', 'group-edit', 'group-view', 'group-delete']; group_path ['group', 'group-add', 'group-edit', 'group-view', 'group-delete'];
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
<div class="col-sm-12 padding-thin"> <div class="col-sm-12 padding-thin">
<div class="box appname"> <div class="box appname">
<div class="col-sm-3 padding-medium" align="center"> <div class="col-sm-3 padding-medium" align="center">
<img src="${home}${logo}" alt=""> <img src="${home}/${logo}" alt="">
</div> </div>
<div class="col-sm-9 padding-high"> <div class="col-sm-9 padding-high">
<span class="about-appname">${request.app_name}</span><br> <span class="about-appname">${request.app_name}</span><br>
...@@ -53,14 +53,14 @@ ...@@ -53,14 +53,14 @@
<div class="col-sm-12 no-padding" align="center"> <div class="col-sm-12 no-padding" align="center">
<div tal:repeat="modul modules" class="col-sm-3 col-xs-6 module padding-thin"> <div tal:repeat="modul modules" class="col-sm-3 col-xs-6 module padding-thin">
<a tal:condition="modul.find('://')<0" <a tal:condition="modul.find('://')<0"
href="${home}${modul}" icon="${modul.replace('/','_')}" class="box"> href="${home}/${modul}" icon="${modul.replace('/','_')}" class="box">
<img alt="" class="icon-modul" src="${home}static/icon/${modul.replace('/','_')}.png"> <img alt="" class="icon-modul" src="${home}/static/icon/${modul.replace('/','_')}.png">
<span>${modules[modul]}</span> <span>${modules[modul]}</span>
</a> </a>
<a tal:condition="modul.find('://')>-1" target="_blank" <a tal:condition="modul.find('://')>-1" target="_blank"
href="${modul}" class="box"> href="${modul}" class="box">
<img alt="" class="icon-modul" <img alt="" class="icon-modul"
src="${home}static/icon/${modul.replace('://','').replace('https','').replace('http','')}.png"> src="${home}/static/icon/${modul.replace('://','').replace('https','').replace('http','')}.png">
<span>${modules[modul]}</span> <span>${modules[modul]}</span>
</a> </a>
</div> </div>
...@@ -74,21 +74,21 @@ ...@@ -74,21 +74,21 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-body">
<h1>ABOUT <span class="bold">OPENSIPKD</span></h1> <h1>ABOUT <span class="bold">OPENSIPKD</span></h1>
<img src="${home}static/img/slide-home-3.jpg" alt=""> <img src="${home}/static/img/slide-home-3.jpg" alt="">
Kami adalah perusahaan yang bergerak di bidang perancangan dan pembuatan aplikasi keuangan yang telah digunakan oleh Pemerintah Daerah.<br> Kami adalah perusahaan yang bergerak di bidang perancangan dan pembuatan aplikasi keuangan yang telah digunakan oleh Pemerintah Daerah.<br>
Aplikasi ini dibangun dengan menggunakan platform Open Source yang terdiri dari : Aplikasi ini dibangun dengan menggunakan platform Open Source yang terdiri dari :
<div class="clearfix" style="margin-top:20px"></div> <div class="clearfix" style="margin-top:20px"></div>
<div class="col-sm-6"> <div class="col-sm-6">
<img class="powered" src="${home}static/img/python.png" alt=""> <a href="https://www.python.org/">Python</a><br> <img class="powered" src="${home}/static/img/python.png" alt=""> <a href="https://www.python.org/">Python</a><br>
<img class="powered" src="${home}static/img/pyramid.png" alt=""> <a href="http://pylonsproject.org/">Pyramid</a><br> <img class="powered" src="${home}/static/img/pyramid.png" alt=""> <a href="http://pylonsproject.org/">Pyramid</a><br>
<a href="https://pypi.python.org/pypi/ziggurat-foundations">Ziggurat Foundations</a><br> <a href="https://pypi.python.org/pypi/ziggurat-foundations">Ziggurat Foundations</a><br>
<a href="http://docs.pylonsproject.org/projects/pyramid-chameleon/en/latest/">Chameleon</a><br> <a href="http://docs.pylonsproject.org/projects/pyramid-chameleon/en/latest/">Chameleon</a><br>
<a href="http://docs.pylonsproject.org/projects/deform/">Deform</a> <a href="http://docs.pylonsproject.org/projects/deform/">Deform</a>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<img class="powered" src="${home}static/img/bootstrap.png" alt=""> <a href="http://getbootstrap.com">Bootstrap</a><br> <img class="powered" src="${home}/static/img/bootstrap.png" alt=""> <a href="http://getbootstrap.com">Bootstrap</a><br>
<img class="powered" src="${home}static/img/smartadmin.png" alt=""> <a href="https://github.com/kalichaudhary/SmartAdmin">Smart Admin</a><br> <img class="powered" src="${home}/static/img/smartadmin.png" alt=""> <a href="https://github.com/kalichaudhary/SmartAdmin">Smart Admin</a><br>
<img class="powered" src="${home}static/img/postgree.png" alt=""> <a href="http://postgresql.org">Postgres SQL</a> <img class="powered" src="${home}/static/img/postgree.png" alt=""> <a href="http://postgresql.org">Postgres SQL</a>
</div> </div>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
...@@ -101,11 +101,11 @@ $( ".module a" ).each(function() { ...@@ -101,11 +101,11 @@ $( ".module a" ).each(function() {
var modul = $(this); var modul = $(this);
var modulenm = modul.attr('icon'); var modulenm = modul.attr('icon');
$.ajax({ $.ajax({
url:'${home}static/icon/'+ modulenm+'.png', url:'${home}/static/icon/'+ modulenm+'.png',
type:'HEAD', type:'HEAD',
error: function() error: function()
{ {
modul.find('img.icon-modul').attr('src','${home}static/icon/default.png'); modul.find('img.icon-modul').attr('src','${home}/static/icon/default.png');
}, },
}); });
}); });
......
<html metal:use-macro="load: ./base3.1.pt" <html metal:use-macro="load: ./base3.1.pt"
tal:define=" tal:define="
home request.route_url('home');"> home request._host;">
<div metal:fill-slot="content"> <div metal:fill-slot="content">
<div class="jarviswidget jarviswidget-color-blueLight"> <!-- jarviswidget --> <div class="jarviswidget jarviswidget-color-blueLight"> <!-- jarviswidget -->
<div tal:content="structure table"></div> <div tal:content="structure table"></div>
......
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" <html lang="en"
tal:define="home request.route_url('home')[:-1];"> tal:define="home request._host;">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
......
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" tal:define="home request.route_url('home');"> <html lang="en" tal:define="home request._host;">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
...@@ -10,22 +10,22 @@ ...@@ -10,22 +10,22 @@
<meta tal:condition="request.google_signin_client_id" <meta tal:condition="request.google_signin_client_id"
name="google-signin-client_id" name="google-signin-client_id"
content="${request.google_signin_client_id}"> content="${request.google_signin_client_id}">
<link rel="shortcut icon" href="${home}static/img/favicon.png"> <link rel="shortcut icon" href="${home}/static/img/favicon.png">
<title>Logout</title> <title>Logout</title>
<!-- Basic Styles --> <!-- Basic Styles -->
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/font-awesome.min.css"> <link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/font-awesome.min.css">
<!-- SmartAdmin Styles : Caution! DO NOT change the order --> <!-- SmartAdmin Styles : Caution! DO NOT change the order -->
<link rel="stylesheet" type="text/css" media="screen" <link rel="stylesheet" type="text/css" media="screen"
href="${home}static/v3/css/smartadmin-production-plugins.min.css"> href="${home}/static/v3/css/smartadmin-production-plugins.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/smartadmin-production.min.css"> <link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/smartadmin-production.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/smartadmin-skins.min.css"> <link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/smartadmin-skins.min.css">
<!-- SmartAdmin RTL Support --> <!-- SmartAdmin RTL Support -->
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/smartadmin-rtl.min.css"> <link rel="stylesheet" type="text/css" media="screen" href="${home}/static/v3/css/smartadmin-rtl.min.css">
<link rel="stylesheet" type="text/css" href="${home}static/css/home.css"> <link rel="stylesheet" type="text/css" href="${home}/static/css/home.css">
</head> </head>
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
tal:repeat="message request.session.pop_flash('error')">${message}</div> tal:repeat="message request.session.pop_flash('error')">${message}</div>
</div> </div>
<div class="col-md-12" align="center"> <div class="col-md-12" align="center">
<img src="${home}static/img/logo.png" <img src="${home}/static/img/logo.png"
class="img-float img-thumbnail" style="height:50px;width:auto;border:none;"/> class="img-float img-thumbnail" style="height:50px;width:auto;border:none;"/>
</div> </div>
<div class="clearfix"></div> <div class="clearfix"></div>
...@@ -83,9 +83,9 @@ ...@@ -83,9 +83,9 @@
<!-- Bootstrap core JavaScript <!-- Bootstrap core JavaScript
================================================== --> ================================================== -->
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="${home}deform_static/scripts/jquery-2.0.3.min.js"></script> <script type="text/javascript" src="${home}/deform_static/scripts/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="${home}deform_static/scripts/bootstrap.min.js"></script> <script type="text/javascript" src="${home}/deform_static/scripts/bootstrap.min.js"></script>
<script type="text/javascript" src="${home}deform_static/scripts/deform.js"></script> <script type="text/javascript" src="${home}/deform_static/scripts/deform.js"></script>
<!--?<script tal:condition="request.google_signin_client_id"--> <!--?<script tal:condition="request.google_signin_client_id"-->
<!--? src="https://apis.google.com/js/platform.js" async defer></script>--> <!--? src="https://apis.google.com/js/platform.js" async defer></script>-->
<!--?<script tal:condition="request.google_signin_client_id">--> <!--?<script tal:condition="request.google_signin_client_id">-->
......
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" <html lang="en"
tal:define=" tal:define="
home request.route_url('home');"> home request._host;">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content=""> <meta name="author" content="">
<link rel="shortcut icon" href="${home}static/img/favicon.png"> <link rel="shortcut icon" href="${home}/static/img/favicon.png">
<title tal:content="request.title"/> <title tal:content="request.title"/>
<link rel="stylesheet" type="text/css" <link rel="stylesheet" type="text/css"
href="${home}static/v3/css/bootstrap.min.css"> href="${home}/static/v3/css/bootstrap.min.css">
</link> </link>
<link rel="stylesheet" type="text/css" <link rel="stylesheet" type="text/css"
href="${home}static/bootstrap/css/font-awesome.min.css"/> href="${home}/static/bootstrap/css/font-awesome.min.css"/>
<link rel="stylesheet" type="text/css" href="${home}deform_static/css/typeahead.css"> <link rel="stylesheet" type="text/css" href="${home}/deform_static/css/typeahead.css">
<link rel="stylesheet" type="text/css" href="${home}static_map/lib/ol4/ol.css"/> <link rel="stylesheet" type="text/css" href="${home}/static_map/lib/ol4/ol.css"/>
<link rel="stylesheet" type="text/css" href="${home}static_map/lib/ol4/ext/ol3-layerswitcher.css"/> <link rel="stylesheet" type="text/css" href="${home}/static_map/lib/ol4/ext/ol3-layerswitcher.css"/>
<link rel="stylesheet" type="text/css" href="${home}static_map/lib/ol4/ext/ol3gm.css"/> <link rel="stylesheet" type="text/css" href="${home}/static_map/lib/ol4/ext/ol3gm.css"/>
<link rel="stylesheet" type="text/css" href="${home}static_map/lib/ol4/ext/ol-geocoder.css"/> <link rel="stylesheet" type="text/css" href="${home}/static_map/lib/ol4/ext/ol-geocoder.css"/>
<link rel="stylesheet" type="text/css" href="${home}static/css/theme.css"> <link rel="stylesheet" type="text/css" href="${home}/static/css/theme.css">
<link rel="stylesheet" type="text/css" href="${home}static/css/navbar-fixed-top.css"> <link rel="stylesheet" type="text/css" href="${home}/static/css/navbar-fixed-top.css">
<link metal:define-slot="link"/> <link metal:define-slot="link"/>
<style> <style>
html{ height:100%;} html{ height:100%;}
...@@ -66,7 +66,7 @@ var gmapKey = '${request.gmap_key}'; ...@@ -66,7 +66,7 @@ var gmapKey = '${request.gmap_key}';
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li class="dropdown"> <li class="dropdown">
<a href="${home}login" class="button">Masuk</a> <a href="${home}/login" class="button">Masuk</a>
</li> </li>
</ul> </ul>
</div> </div>
...@@ -83,30 +83,30 @@ var gmapKey = '${request.gmap_key}'; ...@@ -83,30 +83,30 @@ var gmapKey = '${request.gmap_key}';
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Admin <b class="caret"></b></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Admin <b class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li tal:condition="has_permission(request, 'user')"> <li tal:condition="has_permission(request, 'user')">
<a href="${home}user">User</a></li> <a href="${home}/user">User</a></li>
<li tal:condition="has_permission(request, 'group')"> <li tal:condition="has_permission(request, 'group')">
<a href="${home}group">Group</a></li> <a href="${home}/group">Group</a></li>
<li tal:condition="has_permission(request, 'user-group')"> <li tal:condition="has_permission(request, 'user-group')">
<a href="${home}user/group">User Group</a></li> <a href="${home}/user/group">User Group</a></li>
<li tal:condition="has_permission(request, 'routes')"> <li tal:condition="has_permission(request, 'routes')">
<a href="${home}routes">Routes</a></li> <a href="${home}/routes">Routes</a></li>
<li tal:condition="has_permission(request, 'group-routes')"> <li tal:condition="has_permission(request, 'group-routes')">
<a href="${home}group/routes">Group Permission</a></li> <a href="${home}/group/routes">Group Permission</a></li>
<li tal:condition="has_permission(request, 'upload-logo')"> <li tal:condition="has_permission(request, 'upload-logo')">
<a href="${home}upload/logo">Upload Logo</a></li> <a href="${home}/upload/logo">Upload Logo</a></li>
<li tal:condition="has_permission(request, 'user-ws')"> <li tal:condition="has_permission(request, 'user-ws')">
<a href="${home}user/ws">User Web Service</a></li> <a href="${home}/user/ws">User Web Service</a></li>
</ul> </ul>
</li> </li>
<!-- User Login Menu--> <!-- User Login Menu-->
<li class="dropdown" tal:attributes="class request.path in ['${home}password'] and 'active'"> <li class="dropdown" tal:attributes="class request.path in ['${home}/password'] and 'active'">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">My Account <b class="caret"></b></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown">My Account <b class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="${home}logout">${request.user.nice_username()} Logout</a></li> <li><a href="${home}/logout">${request.user.nice_username()} Logout</a></li>
<li><a href="${home}password">Ubah password</a></li> <li><a href="${home}/password">Ubah password</a></li>
<li tal:condition="'core' in request.modules"> <li tal:condition="'core' in request.modules">
<a href="${home}departemen/chg">Ubah Organisasi</a></li> <a href="${home}/departemen/chg">Ubah Organisasi</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
...@@ -134,16 +134,16 @@ var gmapKey = '${request.gmap_key}'; ...@@ -134,16 +134,16 @@ var gmapKey = '${request.gmap_key}';
</div> </div>
</div> </div>
<script type="text/javascript" <script type="text/javascript"
src="${home}static/v3/js/jquery-2.1.1.min.js"></script> src="${home}/static/v3/js/jquery-2.1.1.min.js"></script>
<script type="text/javascript" <script type="text/javascript"
src="${home}static/v3/js/bootstrap/bootstrap.min.js"></script> src="${home}/static/v3/js/bootstrap/bootstrap.min.js"></script>
<script type="text/javascript" <script type="text/javascript"
src="${home}deform_static/scripts/typeahead.min.js"></script> src="${home}/deform_static/scripts/typeahead.min.js"></script>
<script src="${home}static_map/lib/ol4/ol.js" type="text/javascript"></script> <script src="${home}/static_map/lib/ol4/ol.js" type="text/javascript"></script>
<!-- <script src="${home}static_map/lib/ol4/ol-debug.js" type="text/javascript"></script> --> <!-- <script src="${home}static_map/lib/ol4/ol-debug.js" type="text/javascript"></script> -->
<script type="text/javascript" src="${home}static_map/lib/ol4/ext/ol3-layerswitcher.js"></script> <script type="text/javascript" src="${home}/static_map/lib/ol4/ext/ol3-layerswitcher.js"></script>
<script type="text/javascript" src="${home}static_map/lib/ol4/ext/ol-geocoder.js"></script> <script type="text/javascript" src="${home}/static_map/lib/ol4/ext/ol-geocoder.js"></script>
<script type="text/javascript"> <script type="text/javascript">
if (ol.Map.prototype.getLayer === undefined) { if (ol.Map.prototype.getLayer === undefined) {
ol.Map.prototype.getLayer = function (id) { ol.Map.prototype.getLayer = function (id) {
......
<html metal:use-macro="load: form_input.pt" <html metal:use-macro="load: form_input.pt"
tal:define="home request.route_url('home')[:-1];"> tal:define="home request._host;">
<div metal:fill-slot="scripts"> <div metal:fill-slot="scripts">
<script tal:condition="${captcha}"> <script tal:condition="${captcha}">
......
...@@ -13,12 +13,12 @@ from opensipkd.tools import ( ...@@ -13,12 +13,12 @@ from opensipkd.tools import (
) )
from pyramid.httpexceptions import HTTPFound from pyramid.httpexceptions import HTTPFound
from pyramid.view import view_config from pyramid.view import view_config
from .. import get_urls
# from unggah import DbUpload # from unggah import DbUpload
def route_list(request, p={}): def route_list(request, p={}):
q = dict_to_str(p) q = dict_to_str(p)
return HTTPFound(location=request.route_url('upload-logo', _query=q)) return HTTPFound(location=get_urls(request.route_url('upload-logo', _query=q)))
########## ##########
......
...@@ -47,6 +47,10 @@ class Views(BaseView): ...@@ -47,6 +47,10 @@ class Views(BaseView):
self.edit_schema = EditSchema self.edit_schema = EditSchema
self.add_schema = AddSchema self.add_schema = AddSchema
self.list_buttons = self.list_buttons + self.list_report self.list_buttons = self.list_buttons + self.list_report
path = os.path.dirname(__file__)
path = os.path.dirname(path)
self.report_file = os.path.join(path, 'reports', 'users.jrxml')
def get_bindings(self, row=None): def get_bindings(self, row=None):
status_list = ( status_list = (
...@@ -76,38 +80,38 @@ class Views(BaseView): ...@@ -76,38 +80,38 @@ class Views(BaseView):
@view_config( @view_config(
route_name='user-act', renderer='json', permission='user-view') route_name='user-act', renderer='json', permission='user-view')
def view_act(self): def view_act(self):
url_dict = self.req.matchdict # url_dict = self.req.matchdict
if url_dict['act'] == 'csv': # if url_dict['act'] == 'csv':
query = query_register() # query = query_register()
row = query.first() # row = query.first()
header = row.keys() # header = row.keys()
rows = [list(item) for item in query.all()] # rows = [list(item) for item in query.all()]
filename = 'user.csv' # filename = 'user.csv'
value = { # value = {
'header': header, # 'header': header,
'rows': rows, # 'rows': rows,
} # }
return csv_response(self.req, value, filename) # return csv_response(self.req, value, filename)
#
elif url_dict['act'] == 'pdf': # elif url_dict['act'] == 'pdf':
query = query_register() # query = query_register()
import opensipkd.base # import opensipkd.base
base_path = os.path.dirname(opensipkd.base.__file__) # base_path = os.path.dirname(opensipkd.base.__file__)
path = os.path.join(base_path, 'reports') # path = os.path.join(base_path, 'reports')
rml_row = open_rml_row(path + '/user.row.rml') # rml_row = open_rml_row(path + '/user.row.rml')
rows = [rml_row.format(user_name=r.user_name, email=r.email, # rows = [rml_row.format(user_name=r.user_name, email=r.email,
registered_date=r.registered_date) for r in # registered_date=r.registered_date) for r in
query.all()] # query.all()]
pdf, filename = open_rml_pdf(path + '/user.rml', rows=rows, # pdf, filename = open_rml_pdf(path + '/user.rml', rows=rows,
company=self.req.company, # company=self.req.company,
departement=self.req.departement, # departement=self.req.departement,
address=self.req.address, # address=self.req.address,
base_path=base_path) # base_path=base_path)
filename = os.path.basename(filename) # filename = os.path.basename(filename)
resp = pdf_response(self.req, pdf, filename) # resp = pdf_response(self.req, pdf, filename)
if resp.content_length < 10: # if resp.content_length < 10:
resp.content_length = len(resp.body) # resp.content_length = len(resp.body)
return resp # return resp
return super(Views, self).view_act() return super(Views, self).view_act()
...@@ -347,7 +351,7 @@ class AddSchema(colander.Schema): ...@@ -347,7 +351,7 @@ class AddSchema(colander.Schema):
class EditSchema(AddSchema): class EditSchema(AddSchema):
status = colander.SchemaNode( status = colander.SchemaNode(
colander.String(), widget=status_widget, title=_('Status')) colander.String(), widget=widget.CheckboxWidget(true_val="1", false_val="0"), title=_('Status'))
def get_group_list(): def get_group_list():
...@@ -387,3 +391,33 @@ def query_register(): ...@@ -387,3 +391,33 @@ def query_register():
"DD-MM-YYYY").label( "DD-MM-YYYY").label(
"registered_date")).order_by( "registered_date")).order_by(
User.user_name) User.user_name)
def user_list():
qry = User.query().order_by(User.user_name)
return [(r.id, r.user_name) for r in qry]
def user_select():
result = user_list()
result.insert(0, ('', 'Pilih User'))
return result
@colander.deferred
def user_widget(node, kw):
values = kw.get('user_list', [])
request = kw.get("request")
return widget.SelectWidget(values=values,
placeholder="Pilih User",
style="width:300px;")
class UserFilterSchema(colander.Schema):
user_id = colander.SchemaNode(
colander.Integer(),
widget=user_widget,
oid="user_id",
title="User",
missing=colander.drop,
)
...@@ -19,7 +19,7 @@ from opensipkd.models import ( ...@@ -19,7 +19,7 @@ from opensipkd.models import (
UserGroup, ) UserGroup, )
from datatables import ColumnDT, DataTables from datatables import ColumnDT, DataTables
from .. import get_urls
SESS_ADD_FAILED = 'Tambah user gagal' SESS_ADD_FAILED = 'Tambah user gagal'
SESS_EDIT_FAILED = 'Edit user gagal' SESS_EDIT_FAILED = 'Edit user gagal'
...@@ -160,7 +160,7 @@ def save_request(values, request, row=None): ...@@ -160,7 +160,7 @@ def save_request(values, request, row=None):
def route_list(request): def route_list(request):
return HTTPFound(location=request.route_url('user-group')) return HTTPFound(location=get_urls(request.route_url('user-group')))
def session_failed(request, session_name): def session_failed(request, session_name):
...@@ -186,7 +186,7 @@ def view_add(request): ...@@ -186,7 +186,7 @@ def view_add(request):
c = form.validate(controls) c = form.validate(controls)
except ValidationFailure as e: except ValidationFailure as e:
request.session[SESS_ADD_FAILED] = e.render() request.session[SESS_ADD_FAILED] = e.render()
return HTTPFound(location=request.route_url('user-group-add')) return HTTPFound(location=get_urls(request.route_url('user-group-add')))
save_request(controls_dicted, request) save_request(controls_dicted, request)
return route_list(request) return route_list(request)
elif SESS_ADD_FAILED in request.session: elif SESS_ADD_FAILED in request.session:
...@@ -225,8 +225,8 @@ def view_edit(request): ...@@ -225,8 +225,8 @@ def view_edit(request):
c = form.validate(controls) c = form.validate(controls)
except ValidationFailure as e: except ValidationFailure as e:
request.session[SESS_EDIT_FAILED] = e.render() request.session[SESS_EDIT_FAILED] = e.render()
return HTTPFound(location=request.route_url('user-group-edit', return HTTPFound(location=get_urls(request.route_url('user-group-edit',
id=row.id)) id=row.id)))
save_request(dict(controls), request, row) save_request(dict(controls), request, row)
return route_list(request) return route_list(request)
elif SESS_EDIT_FAILED in request.session: elif SESS_EDIT_FAILED in request.session:
......
...@@ -44,7 +44,7 @@ from pyramid_mailer.message import Message ...@@ -44,7 +44,7 @@ from pyramid_mailer.message import Message
from opensipkd.tools.buttons import btn_cancel from opensipkd.tools.buttons import btn_cancel
from opensipkd.tools.form_api import formfield2dict from opensipkd.tools.form_api import formfield2dict
from .. import get_urls
log = __import__("logging").getLogger(__name__) log = __import__("logging").getLogger(__name__)
...@@ -168,11 +168,11 @@ class ViewLogin(BaseView): ...@@ -168,11 +168,11 @@ class ViewLogin(BaseView):
next_url = request.params.get('next', request.referrer) next_url = request.params.get('next', request.referrer)
login_tpl = get_params('login_tpl', 'templates/login.pt') login_tpl = get_params('login_tpl', 'templates/login.pt')
if not next_url: if not next_url:
next_url = request.route_url('home') next_url = get_urls(request.route_url('home'))
if request.authenticated_userid: # (request): if request.authenticated_userid: # (request):
request.session.flash('Anda sudah login', 'error') request.session.flash('Anda sudah login', 'error')
return HTTPFound(location=f"{request.route_url('home')}") return HTTPFound(location=get_urls(f"{request.route_url('home')}"))
schema = Login(validator=login_validator) schema = Login(validator=login_validator)
form = Form(schema, buttons=('login',)) form = Form(schema, buttons=('login',))
...@@ -187,7 +187,7 @@ class ViewLogin(BaseView): ...@@ -187,7 +187,7 @@ class ViewLogin(BaseView):
msg = 'Login gagal' msg = 'Login gagal'
set_user_log(msg, request, log, identity) set_user_log(msg, request, log, identity)
request.session.flash(msg, 'error') request.session.flash(msg, 'error')
return HTTPFound(location=request.route_url('login')) return HTTPFound(location=get_urls(request.route_url('login')))
values = dict(c) values = dict(c)
# start cek external module # start cek external module
...@@ -206,19 +206,19 @@ class ViewLogin(BaseView): ...@@ -206,19 +206,19 @@ class ViewLogin(BaseView):
except Exception as e: except Exception as e:
log.warn(str(e)) log.warn(str(e))
request.session.flash(str(e), "error") request.session.flash(str(e), "error")
return HTTPFound(location=request.route_url('login')) return HTTPFound(location=get_urls(request.route_url('login')))
else: else:
login = LoginUser(self.req) login = LoginUser(self.req)
if not login.login(values, user): if not login.login(values, user):
request.session.flash(login.message, "error") request.session.flash(login.message, "error")
next_url = f"{request.route_url('login')}?next={next_url}" next_url = get_urls(f"{request.route_url('login')}?next={next_url}")
return HTTPFound(location=next_url) return HTTPFound(location=next_url)
return redirect_login(request, user) return redirect_login(request, user)
elif 'register' in request.POST: elif 'register' in request.POST:
register_form = get_params("register_form", 'register') register_form = get_params("register_form", 'register')
return HTTPFound(location=request.route_url(register_form)) return HTTPFound(location=get_urls(request.route_url(register_form)))
elif 'login failed' in request.session: elif 'login failed' in request.session:
r = dict(form=request.session['login failed']) r = dict(form=request.session['login failed'])
...@@ -236,13 +236,13 @@ class ViewLogin(BaseView): ...@@ -236,13 +236,13 @@ class ViewLogin(BaseView):
login_tpl, dict( login_tpl, dict(
form=form.render(), form=form.render(),
message=message, message=message,
url=request.route_url('login'), url=get_urls(request.route_url('login')),
next_url=next_url, next_url=next_url,
login=login, ), login=login, ),
request=request) request=request)
except Oauth2UserExc as e: except Oauth2UserExc as e:
request.session.flash(str(e), 'error') request.session.flash(str(e), 'error')
return HTTPFound(location=request.route_url('login')) return HTTPFound(location=get_urls(request.route_url('login')))
if user and user.status == 1: if user and user.status == 1:
return redirect_login(request, user) return redirect_login(request, user)
...@@ -250,7 +250,7 @@ class ViewLogin(BaseView): ...@@ -250,7 +250,7 @@ class ViewLogin(BaseView):
if login_tpl == 'templates/login.pt': if login_tpl == 'templates/login.pt':
return dict(form=form.render(), return dict(form=form.render(),
message=message, message=message,
url=request.route_url('login'), url=get_urls(request.route_url('login')),
next_url=next_url, next_url=next_url,
login=login, ) login=login, )
...@@ -259,7 +259,7 @@ class ViewLogin(BaseView): ...@@ -259,7 +259,7 @@ class ViewLogin(BaseView):
request=request, request=request,
value=dict(form=form.render(), value=dict(form=form.render(),
message=message, message=message,
url=request.route_url('login'), url=get_urls(request.route_url('login')),
next_url=next_url, next_url=next_url,
login=login, ), login=login, ),
) )
...@@ -272,7 +272,7 @@ def redirect_login(request, user): ...@@ -272,7 +272,7 @@ def redirect_login(request, user):
next_url = request.params.get('next') next_url = request.params.get('next')
if not next_url and request.matched_route.name == 'login': if not next_url and request.matched_route.name == 'login':
url = get_params('modules_default', 'home') url = get_params('modules_default', 'home')
return HTTPFound(location=request.route_url(url), return HTTPFound(location=get_urls(request.route_url(url)),
headers=headers) headers=headers)
return HTTPFound(location=next_url, headers=headers) return HTTPFound(location=next_url, headers=headers)
...@@ -299,8 +299,8 @@ class Logout(BaseView): ...@@ -299,8 +299,8 @@ class Logout(BaseView):
form = self.get_form(LogoutSchema, buttons=(btn_cancel, btn_logout)) form = self.get_form(LogoutSchema, buttons=(btn_cancel, btn_logout))
if 'cancel' in request.POST or "home" in request.POST: if 'cancel' in request.POST or "home" in request.POST:
log.info(request.route_url('home')) log.info(get_urls(request.route_url('home')))
return HTTPFound(location=f"{request.route_url('home')}", ) return HTTPFound(location=get_urls(f"{request.route_url('home')}", ))
elif "logout" in request.POST: elif "logout" in request.POST:
form = self.get_form(LogoutSchema, buttons=(btn_home,)) form = self.get_form(LogoutSchema, buttons=(btn_home,))
...@@ -343,7 +343,7 @@ def change_password_validator(form, value): ...@@ -343,7 +343,7 @@ def change_password_validator(form, value):
def view_change_password(request): def view_change_password(request):
if request.authenticated_userid: if request.authenticated_userid:
request.session.flash('Anda sudah login', 'error') request.session.flash('Anda sudah login', 'error')
return HTTPFound(location=f"{request.route_url('home')}") return HTTPFound(location=get_urls(f"{request.route_url('home')}"))
schema = ChangePassword(validator=change_password_validator) schema = ChangePassword(validator=change_password_validator)
btn_save = Button('save', _('Simpan')) btn_save = Button('save', _('Simpan'))
...@@ -353,7 +353,7 @@ def view_change_password(request): ...@@ -353,7 +353,7 @@ def view_change_password(request):
if not request.POST: if not request.POST:
return dict(form=form.render()) return dict(form=form.render())
if 'save' not in request.POST: if 'save' not in request.POST:
return HTTPFound(location=request.route_url('login')) return HTTPFound(location=get_urls(request.route_url('login')))
items = request.POST.items() items = request.POST.items()
try: try:
c = form.validate(items) c = form.validate(items)
...@@ -365,7 +365,7 @@ def view_change_password(request): ...@@ -365,7 +365,7 @@ def view_change_password(request):
if not user or \ if not user or \
create_now() - user.security_code_date > one_hour: create_now() - user.security_code_date > one_hour:
request.session.flash('Security code expired', 'error') request.session.flash('Security code expired', 'error')
return HTTPFound(location=request.route_url('login')) return HTTPFound(location=get_urls(request.route_url('login')))
user.security_code = None user.security_code = None
UserService.set_password(user, c['new_password']) UserService.set_password(user, c['new_password'])
...@@ -373,7 +373,7 @@ def view_change_password(request): ...@@ -373,7 +373,7 @@ def view_change_password(request):
headers = get_login_headers(request, user) headers = get_login_headers(request, user)
request.session.flash('Password baru Anda sudah disimpan.') request.session.flash('Password baru Anda sudah disimpan.')
set_user_log("Change Password", request, log) set_user_log("Change Password", request, log)
return HTTPFound(location=f"{request.route_url('home')}", headers=headers) return HTTPFound(location=get_urls(f"{request.route_url('home')}"), headers=headers)
###################### ######################
...@@ -403,12 +403,12 @@ def view_recreate_api_key(request): ...@@ -403,12 +403,12 @@ def view_recreate_api_key(request):
d = dict(api_key=request.user.api_key) d = dict(api_key=request.user.api_key)
return dict(form=form.render(appstruct=d)) return dict(form=form.render(appstruct=d))
if 'recreate' not in request.POST: if 'recreate' not in request.POST:
return HTTPFound(location=f"{request.route_url('home')}") return HTTPFound(location=get_urls(f"{request.route_url('home')}"))
request.user.api_key = api_key = generate_api_key() request.user.api_key = api_key = generate_api_key()
DBSession.add(request.user) DBSession.add(request.user)
msg = 'API Key Anda yang baru {}'.format(api_key) msg = 'API Key Anda yang baru {}'.format(api_key)
request.session.flash(msg) request.session.flash(msg)
return HTTPFound(location=f"{request.route_url('home')}") return HTTPFound(location=get_urls(f"{request.route_url('home')}"))
################## ##################
...@@ -432,7 +432,9 @@ def reset_password_validator(form, value): ...@@ -432,7 +432,9 @@ def reset_password_validator(form, value):
def security_code_age(user): def security_code_age(user):
now = create_now() now = create_now()
return now - user.security_code_date if user.security_code_date:
return now - user.security_code_date
return timedelta(minutes=1)
def send_email_security_code( def send_email_security_code(
...@@ -508,7 +510,7 @@ def regenerate_security_code(user, hour=1.0): ...@@ -508,7 +510,7 @@ def regenerate_security_code(user, hour=1.0):
renderer='templates/reset-password.pt') renderer='templates/reset-password.pt')
def view_reset_password(request): def view_reset_password(request):
if request.authenticated_userid: if request.authenticated_userid:
return HTTPFound(location=f"{request.route_url('home')}") return HTTPFound(location=get_urls(f"{request.route_url('home')}"))
resp = dict(title=_('Reset password')) resp = dict(title=_('Reset password'))
schema = ResetPassword(validator=reset_password_validator) schema = ResetPassword(validator=reset_password_validator)
...@@ -530,7 +532,7 @@ def view_reset_password(request): ...@@ -530,7 +532,7 @@ def view_reset_password(request):
send_email_security_code( send_email_security_code(
request, user, remain, 'Reset password', 'reset-password-body', request, user, remain, 'Reset password', 'reset-password-body',
'reset-password-body.tpl') 'reset-password-body.tpl')
return HTTPFound(location=request.route_url('reset-password-sent')) return HTTPFound(location=get_urls(request.route_url('reset-password-sent')))
resp['form'] = form.render() resp['form'] = form.render()
return resp return resp
......
...@@ -3,8 +3,12 @@ import logging ...@@ -3,8 +3,12 @@ import logging
from deform.widget import ( from deform.widget import (
SchemaType, SchemaType,
DateInputWidget as DeformDateInputWidget) DateInputWidget as DeformDateInputWidget,
from colander import null, Invalid default_resources, ResourceRegistry, default_resource_registry, _StrippedString, Widget)
from colander import null, Invalid, SchemaNode, Mapping
_logging = logging.getLogger(__name__)
class _FieldStorage(SchemaType): class _FieldStorage(SchemaType):
def deserialize(self, node, cstruct): def deserialize(self, node, cstruct):
...@@ -16,52 +20,48 @@ class _FieldStorage(SchemaType): ...@@ -16,52 +20,48 @@ class _FieldStorage(SchemaType):
return cstruct return cstruct
class DateInputWidget(DeformDateInputWidget): # default_resources = {
""" # "jquery.form": {None: {"js": "deform:static/scripts/jquery.form-3.09.js"}},
Renders a date picker widget. # "jquery.maskedinput": {
# None: {"js": "deform:static/scripts/jquery.maskedinput-1.3.1.min.js"}
The default rendering is as a native HTML5 date input widget, # },
falling back to pickadate (https://github.com/amsul/pickadate.js.) # "jquery.maskMoney": {
# None: {"js": "deform:static/scripts/jquery.maskMoney-3.1.1.min.js"}
Most useful when the schema node is a ``colander.Date`` object. # },
# "deform": {
**Attributes/Arguments** # None: {
# "js": (
options # "deform:static/scripts/jquery.form-3.09.js",
Dictionary of options for configuring the widget (eg: date format) # "deform:static/scripts/deform.js",
# )
template # }
The template name used to render the widget. Default: # },
``dateinput``. # "typeahead": {
# None: {
readonly_template # "js": "deform:static/scripts/typeahead.min.js",
The template name used to render the widget in read-only mode. # "css": "deform:static/css/typeahead.css",
Default: ``readonly/textinput``. # }
""" # },
default_options = ( # "modernizr": {
("format", "yyyy-mm-dd"), # None: {
("selectMonths", True), # "js": "deform:static/scripts/modernizr.custom.input-types-and-atts.js" # noQA
("selectYears", True), # }
("formatSubmit", "yyyy-mm-dd"), # },
) # "pickadate": {
def serialize(self, field, cstruct, **kw): # None: {
if cstruct in (null, None): # "js": (
cstruct = "" # "static/pickadate/lib/picker.js",
readonly = kw.get("readonly", self.readonly) # "static/pickadate/lib/picker.date.js",
template = readonly and self.readonly_template or self.template # "static/pickadate/lib/picker.time.js",
options = dict( # "static/pickadate/lib/legacy.js",
kw.get("options") or self.options or self.default_options # ),
) # "css": (
kw.setdefault("options_json", json.dumps(options)) # "static/pickadate/lib/themes/default.css",
values = self.get_template_values(field, cstruct, kw) # "static/pickadate/lib/themes/default.date.css",
return field.renderer(template, **values) # "static/pickadate/lib/themes/default.time.css",
# ),
def deserialize(self, field, pstruct): # }
logging.debug(f"widget: {field} {pstruct}") # },
if pstruct in ("", null): # }
return null #
try: # default_resource_registry = ResourceRegistry()
validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc:
raise Invalid(field.schema, "Invalid pstruct: %s" % exc)
return validated["date_submit"] or validated["date"]
import json import json
import logging import logging
from colander import SchemaNode, null, Mapping, Invalid, text_, string_types from colander import SchemaNode, null, Mapping, Invalid, string_types
from deform.widget import Widget, _StrippedString, Select2Widget from deform.widget import Widget, _StrippedString, Select2Widget, default_resources, \
ResourceRegistry, default_resource_registry
from deform.form import Button
from iso8601.iso8601 import ISO8601_REGEX
from deform.i18n import _
from colander import compat
from deform import widget
_logging = logging.getLogger(__name__) _logging = logging.getLogger(__name__)
...@@ -46,7 +51,7 @@ class DokumenWidget(Widget): ...@@ -46,7 +51,7 @@ class DokumenWidget(Widget):
try: try:
validated = self._pstruct_schema.deserialize(pstruct) validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc: except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc)) raise Invalid(field.schema, f"Invalid pstruct: {exc}")
jenis = validated["jenis"] jenis = validated["jenis"]
year = validated["year"] year = validated["year"]
bundle = validated["bundle"] bundle = validated["bundle"]
...@@ -101,7 +106,7 @@ class FormulirWidget(Widget): ...@@ -101,7 +106,7 @@ class FormulirWidget(Widget):
try: try:
validated = self._pstruct_schema.deserialize(pstruct) validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc: except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc)) raise Invalid(field.schema, f"Invalid pstruct: {exc}")
year = validated["year"] year = validated["year"]
bundle = validated["bundle"] bundle = validated["bundle"]
seq = validated["seq"] seq = validated["seq"]
...@@ -154,7 +159,7 @@ class BlokKavNoWidget(Widget): ...@@ -154,7 +159,7 @@ class BlokKavNoWidget(Widget):
try: try:
validated = self._pstruct_schema.deserialize(pstruct) validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc: except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc)) raise Invalid(field.schema, f"Invalid pstruct: {exc}")
blok_kav_no = validated["blok_kav_no"] blok_kav_no = validated["blok_kav_no"]
rt = validated["rt"] rt = validated["rt"]
rw = validated["rw"] rw = validated["rw"]
...@@ -187,6 +192,8 @@ class Select2MsWidget(Select2Widget): ...@@ -187,6 +192,8 @@ class Select2MsWidget(Select2Widget):
""" """
url = ""
slave = ""
template = "select2_ms.pt" template = "select2_ms.pt"
...@@ -221,7 +228,7 @@ class QtyWidget(Widget): ...@@ -221,7 +228,7 @@ class QtyWidget(Widget):
try: try:
validated = self._pstruct_schema.deserialize(pstruct) validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc: except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc)) raise Invalid(field.schema, f"Invalid pstruct: {exc}")
qty = validated["qty"] qty = validated["qty"]
measure = validated["measure"] measure = validated["measure"]
...@@ -375,7 +382,7 @@ class MapWidget(Widget): ...@@ -375,7 +382,7 @@ class MapWidget(Widget):
{ {
"js": "opensipkd.base:static/js/gmap.js", "js": "opensipkd.base:static/js/gmap.js",
"css": "deform:static/select2/select2.css", "css": "deform:static/select2/select2.css",
},) },)
def __init__(self, **kw): def __init__(self, **kw):
super().__init__(**kw) super().__init__(**kw)
...@@ -493,3 +500,206 @@ class LeafMapWidget(Widget): ...@@ -493,3 +500,206 @@ class LeafMapWidget(Widget):
if not pstruct: if not pstruct:
return null return null
return pstruct return pstruct
class BootStrapDateInputWidget(Widget):
"""
Renders a date picker widget.
The default rendering is as a native HTML5 date input widget,
falling back to pickadate (https://github.com/amsul/pickadate.js.)
Most useful when the schema node is a ``colander.Date`` object.
**Attributes/Arguments**
options
Dictionary of options for configuring the widget (eg: date format)
template
The template name used to render the widget. Default:
``dateinput``.
readonly_template
The template name used to render the widget in read-only mode.
Default: ``readonly/textinput``.
"""
template = "bootstrapdateinput"
readonly_template = "readonly/textinput"
type_name = "text"
req_path = "opensipkd.base:static/v3/js/plugin"
requirements = (
('deform', None),
{
"js": (
f"{req_path}/bootstrap-datepicker/js/bootstrap-datepicker.min.js",
f"{req_path}/bootstrap-timepicker/bootstrap-timepicker.min.js",
f"{req_path}/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js",
),
"css": (
f"{req_path}/bootstrap-datepicker/css/bootstrap-datepicker.min.css",
# f"{req_path}/bootstrap-timepicker/css/bootstrap-timepicker.min.css",
f"{req_path}/bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css",
),
}
)
default_options = (
("format", "yyyy-mm-dd"),
)
# ("selectMonths", True),
# ("selectYears", True),
options = None
_pstruct_schema = SchemaNode(
Mapping(),
SchemaNode(_StrippedString(), name="date"),
SchemaNode(_StrippedString(), name="date_submit", missing=""),
)
def serialize(self, field, cstruct, **kw):
if cstruct in (null, None):
cstruct = ""
readonly = kw.get("readonly", self.readonly)
template = readonly and self.readonly_template or self.template
options = dict(
kw.get("options") or self.options or self.default_options
)
options["formatSubmit"] = "yyyy-mm-dd"
kw.setdefault("options_json", json.dumps(options))
values = self.get_template_values(field, cstruct, kw)
return field.renderer(template, **values)
def deserialize(self, field, pstruct):
if pstruct in ("", null):
return null
try:
validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc:
raise Invalid(field.schema, "Invalid pstruct: %s" % exc)
return validated["date_submit"] or validated["date"]
class BootStrapDateTimeInputWidget(Widget):
"""
Renders a datetime picker widget.
The default rendering is as a pair of inputs (a date and a time) using
pickadate.js (https://github.com/amsul/pickadate.js).
Used for ``colander.DateTime`` schema nodes.
**Attributes/Arguments**
date_options
A dictionary of date options passed to pickadate.
time_options
A dictionary of time options passed to pickadate.
template
The template name used to render the widget. Default:
``dateinput``.
readonly_template
The template name used to render the widget in read-only mode.
Default: ``readonly/textinput``.
"""
template = "datetimeinput"
readonly_template = "readonly/datetimeinput"
type_name = "datetime"
requirements = (("modernizr", None), ("pickadate", None))
default_date_options = (
("format", "yyyy-mm-dd"),
("selectMonths", True),
("selectYears", True),
)
date_options = None
default_time_options = (("format", "h:i A"), ("interval", 30))
time_options = None
_pstruct_schema = SchemaNode(
Mapping(),
SchemaNode(_StrippedString(), name="date"),
SchemaNode(_StrippedString(), name="time"),
SchemaNode(_StrippedString(), name="date_submit", missing=""),
SchemaNode(_StrippedString(), name="time_submit", missing=""),
)
def serialize(self, field, cstruct, **kw):
if cstruct in (null, None):
cstruct = ""
readonly = kw.get("readonly", self.readonly)
if cstruct:
parsed = ISO8601_REGEX.match(cstruct)
if parsed: # strip timezone if it's there
timezone = parsed.groupdict()["timezone"]
if timezone and cstruct.endswith(timezone):
cstruct = cstruct[: -len(timezone)]
try:
date, time = cstruct.split("T", 1)
try:
# get rid of milliseconds
time, _ = time.split(".", 1)
except ValueError:
pass
kw["date"], kw["time"] = date, time
except ValueError: # need more than one item to unpack
kw["date"] = kw["time"] = ""
date_options = dict(
kw.get("date_options")
or self.date_options
or self.default_date_options
)
date_options["formatSubmit"] = "yyyy-mm-dd"
kw["date_options_json"] = json.dumps(date_options)
time_options = dict(
kw.get("time_options")
or self.time_options
or self.default_time_options
)
time_options["formatSubmit"] = "HH:i"
kw["time_options_json"] = json.dumps(time_options)
values = self.get_template_values(field, cstruct, kw)
template = readonly and self.readonly_template or self.template
return field.renderer(template, **values)
def deserialize(self, field, pstruct):
if pstruct is null:
return null
else:
try:
validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc:
raise Invalid(field.schema, "Invalid pstruct: %s" % exc)
# seriously pickadate? oh. right. i forgot. you're javascript.
date = validated["date_submit"] or validated["date"]
time = validated["time_submit"] or validated["time"]
if not time and not date:
return null
result = "T".join([date, time])
if not date:
raise Invalid(field.schema, _("Incomplete date"), result)
if not time:
raise Invalid(field.schema, _("Incomplete time"), result)
return result
class TextInputWidget(widget.TextInputWidget):
template = "textinput_btn"
button = None
def __init__(self, **kw):
super(TextInputWidget, self).__init__(**kw)
if isinstance(self.button, compat.string_types):
self.button = Button(self.button, type="button")
<div tal:define="css_class css_class|field.widget.css_class;
oid oid|field.oid;
style style|field.widget.style;
type_name type_name|field.widget.type_name;"
tal:omit-tag="">
${field.start_mapping()}
<input type="${type_name}"
name="date"
value="${cstruct}"
tal:attributes="class string: ${css_class or ''} form-control hasDatepicker;
style style;
attributes|field.widget.attributes|{'readonly':'true'};"
id="${oid}"/>
${field.end_mapping()}
<script type="text/javascript">
deform.addCallback(
'${oid}',
function deform_cb(oid) {
$('#'+oid).datepicker(${options_json});
//if (!Modernizr.inputtypes['date'] ||"${type_name}" != "date" || window.forceDateTimePolyfill){
// $('#' + oid).pickadate(${options_json});
//}
}
);
</script>
</div>
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
oid oid|field.oid; oid oid|field.oid;
true_val true_val|field.widget.true_val;" true_val true_val|field.widget.true_val;"
i18n:domain="deform"> i18n:domain="deform">
<p class="deform-readonly-true form-control-static" <p class="deform-readonly-true"
id="${oid}" id="${oid}"
tal:condition="cstruct == true_val" tal:condition="cstruct == true_val"
i18n:translate="">True</p> i18n:translate=""><i class="fas fa-check-square" aria-hidden="true"></i></p>
<p class="deform-readonly-false form-control-static" <p class="deform-readonly-false"
id="${oid}" id="${oid}"
tal:condition="cstruct != true_val" tal:condition="cstruct != true_val"
i18n:translate="">False</p> i18n:translate=""><i class="fas fa-window-close" aria-hidden="true"></i></p>
</div> </div>
<div tal:define=" <div tal:define="
name name|field.name; name name|field.name;
style field.widget.style; style field.widget.style;
oid oid|field.oid; oid oid|field.oid;
css_class css_class|field.widget.css_class; css_class css_class|field.widget.css_class;
unicode unicode|str; unicode unicode|str;
optgroup_class optgroup_class|field.widget.optgroup_class; optgroup_class optgroup_class|field.widget.optgroup_class;
multiple multiple|field.widget.multiple; multiple multiple|field.widget.multiple;
url url|field.widget.url; url url|field.widget.url;
slave slave|field.widget.slave;" slave slave|field.widget.slave;"
tal:omit-tag=""> tal:omit-tag="">
<style> <style>
.select2-selection.form-control { .select2-selection.form-control {
padding: 0px 0px; padding: 0px 0px;
} }
.select2-container--default .select2-selection--multiple, .select2-container--default .select2-selection--multiple,
.select2-container--default .select2-selection--single { .select2-container--default .select2-selection--single {
border: 1px solid #ccc; border: 1px solid #ccc;
} }
</style> </style>
<input type="hidden" name="__start__" value="${name}:sequence" <input type="hidden" name="__start__" value="${name}:sequence"
tal:condition="multiple" /> tal:condition="multiple" />
<select tal:attributes=" <select tal:attributes="
name name; name name;
id oid; id oid;
class string: form-control ${css_class or ''}; class string: form-control ${css_class or ''};
data-placeholder field.widget.placeholder|None; data-placeholder field.widget.placeholder|None;
multiple multiple; multiple multiple;
style style; style style;
attributes|field.widget.attributes|{};"> attributes|field.widget.attributes|{};">
<tal:loop tal:repeat="item values"> <tal:loop tal:repeat="item values">
<optgroup tal:condition="isinstance(item, optgroup_class)" <optgroup tal:condition="isinstance(item, optgroup_class)"
tal:attributes="label item.label"> tal:attributes="label item.label">
<option tal:repeat="(value, description) item.options" <option tal:repeat="(value, description) item.options"
tal:attributes=" tal:attributes="
selected python:field.widget.get_select_value(cstruct, value); selected python:field.widget.get_select_value(cstruct, value);
class css_class; class css_class;
label field.widget.long_label_generator and description; label field.widget.long_label_generator and description;
value value" value value"
tal:content="field.widget.long_label_generator and field.widget.long_label_generator(item.label, description) or description"/> tal:content="field.widget.long_label_generator and field.widget.long_label_generator(item.label, description) or description"/>
</optgroup> </optgroup>
<option tal:condition="not isinstance(item, optgroup_class)" <option tal:condition="not isinstance(item, optgroup_class)"
tal:attributes=" tal:attributes="
selected python:field.widget.get_select_value(cstruct, item[0]); selected python:field.widget.get_select_value(cstruct, item[0]);
class css_class; class css_class;
value item[0]">${item[1]}</option> value item[0]">${item[1]}</option>
</tal:loop> </tal:loop>
</select> </select>
<script type="text/javascript"> <script type="text/javascript">
deform.addCallback( deform.addCallback(
'${field.oid}', '${field.oid}',
function(oid) { function (oid) {
$('#' + oid).select2({ $('#' + oid).select2({
containerCssClass: 'form-control', containerCssClass: 'form-control',
placeholder: "${str(field.widget.placeholder).replace('"','\\"')|""}" || undefined, placeholder: "${str(field.widget.placeholder).replace('"','\\"')|""}" || undefined,
allowClear: "${hasattr(field.widget, 'placeholder')}", allowClear: "${hasattr(field.widget, 'placeholder')}",
tags: ${str(getattr(field.widget, 'tags', 'undefined')).lower()} tags: ${str(getattr(field.widget, 'tags', 'undefined')).lower()}
}); });
} }
); );
</script> </script>
<script type="text/javascript" tal:condition="url and slave"> <script type="text/javascript" tal:condition="url and slave">
deform.addCallback( deform.addCallback(
'${field.oid}', '${field.oid}',
function(oid) { function (oid) {
$('#' + oid).change(function () { $('#' + oid).change(function () {
$("#${slave}").val(""); $("#${slave}").val("");
$("#${slave}").empty(); $("#${slave}").empty();
$("#${slave}").append('<option value="" selected disabled>Pilih Data...</option>'); $("#${slave}").append('<option value="" selected disabled>Pilih Data...</option>');
let value = $(this).val(); let value = $(this).val();
if (value) { if (value) {
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: "${url}" + value, url: "${url}" + value,
success: function (res) { success: function (res) {
if (res) { if (res) {
$.each(res, function (key, value) { $.each(res, function (key, value) {
$("#${slave}").append('<option value="' + key + '">' + value + '</option>'); $("#${slave}").append('<option value="' + key + '">' + value + '</option>');
}); });
} else { } else {
$("#${slave}").empty(); $("#${slave}").empty();
} }
}
});
} }
$("#${slave}").change();
}); });
} });
$("#${slave}").change();
});
});
</script> </script>
<input type="hidden" name="__end__" value="${name}:sequence" <input type="hidden" name="__end__" value="${name}:sequence"
tal:condition="multiple" /> tal:condition="multiple" />
</div> </div>
<span tal:define="name name|field.name;
css_class css_class|field.widget.css_class;
oid oid|field.oid;
mask mask|field.widget.mask;
button button|field.widget.button;
mask_placeholder mask_placeholder|field.widget.mask_placeholder;
style style|field.widget.style;
" tal:omit-tag="">
<input type="text" tal:attributes="class string: form-control ${css_class or ''};
style style;
attributes|field.widget.attributes|{};" id="${oid}" name="${name}" value="${cstruct}"
tal:condition="not button" />
<div class="input-group" tal:condition="button">
<input type="text" name="${name}" value="${cstruct}" tal:attributes="class string: form-control ${css_class or ''};
style style;
attributes|field.widget.attributes|{};" id="${oid}" />
<span class="input-group-btn">
<button tal:define="btn_disposition 'btn-default';" tal:attributes="disabled button.disabled if button.disabled else None;
attributes|button.attributes|{};" id="${oid+button.name}" name="${button.name}"
type="${button.type}" class="btn ${button.css_class or btn_disposition}" value="${button.value}"
tal:condition="button.type != 'link'">
<span tal:condition="button.icon" class="glyphicon glyphicon-${button.icon}"></span>
${button.title}
</button>
<a tal:define="btn_disposition 'btn-default';
btn_href button.value|''" class="btn ${button.css_class or btn_disposition}" id="${oid + button.name}"
href="${btn_href}" tal:condition="button.type == 'link'">
<span tal:condition="button.icon" class="glyphicon glyphicon-${button.icon}"></span>
${button.title}
</a>
</span>
</div><!-- /input-group -->
<script tal:condition="mask" type="text/javascript">
deform.addCallback(
'${oid}',
function (oid) {
$("#" + oid).mask("${mask}",
{ placeholder: "${mask_placeholder}" });
});
</script>
</span>
\ No newline at end of file \ No newline at end of file
...@@ -109,6 +109,7 @@ class DeTable(field.Field): ...@@ -109,6 +109,7 @@ class DeTable(field.Field):
paginates='true', paginates='true',
params="", params="",
server_side='true', server_side='true',
state_save=True,
data=[], data=[],
allow_edit=True, allow_edit=True,
allow_delete=True, allow_delete=True,
...@@ -246,6 +247,7 @@ class DeTable(field.Field): ...@@ -246,6 +247,7 @@ class DeTable(field.Field):
self.sorts = sorts self.sorts = sorts
self.paginates = paginates self.paginates = paginates
self.filters = filters self.filters = filters
self.state_save = json.dumps(state_save)
class Button(object): class Button(object):
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
allow_edit allow_edit|field.allow_edit; allow_edit allow_edit|field.allow_edit;
allow_delete allow_delete|field.allow_delete; allow_delete allow_delete|field.allow_delete;
allow_view allow_view|field.allow_view; allow_view allow_view|field.allow_view;
state_save state_save|field.state_save;
" "
tal:attributes="style style; class css_class; attributes|field.widget.attributes|{};" tal:attributes="style style; class css_class; attributes|field.widget.attributes|{};"
i18n:domain="detable" i18n:domain="detable"
...@@ -68,46 +69,53 @@ ...@@ -68,46 +69,53 @@
return 'Archived'; return 'Archived';
} }
function render_checklist(value) {
return '<input type="checkbox" checked="'+{value}+'"></input>';
}
for (let co in ${tableid}Columns) { for (let co in ${tableid}Columns) {
if (${tableid}Columns[co].checkbox === true) { if (${tableid}Columns[co].checkbox === true) {
${tableid}Columns[co].className = "text-center"; ${tableid}Columns[co].className = "text-center";
${tableid}Columns[co].width = "30pt"; ${tableid}Columns[co].width = "30pt";
${tableid}Columns[co].render = function (val) { ${tableid}Columns[co].render = function (val) {
if (["", false, 0].indexOf(val) === -1) { if (["", false, 0].indexOf(val) === -1) {
return render_checkbox(true); return render_checkbox(true);
} else return render_checkbox(false); } else return render_checkbox(false);
}
} else if (${tableid}Columns[co].hasOwnProperty("url")) {
let url = ${tableid}Columns[co].url;
${tableid}Columns[co].render = function (data) {
let result = "No Data"
if (data != null) {
result = '<a href="' + url + data + '" target="_blank">Link</a>&nbsp;';
} }
return result;
} }
} else if (${tableid}Columns[co].data === "id" && ${tableid}Columns[co].action === true) { else if (${tableid}Columns[co].hasOwnProperty("url")) {
${tableid}Columns[co].render = function (id) { let url = ${tableid}Columns[co].url;
let result = "" ${tableid}Columns[co].render = function (data) {
if (${allow_view}) { let result = "No Data"
result = '<a href="${url}/' + id + '/view"><i class="fas fa-eye" aria-hidden="true"></i></a>&nbsp;'; if (data != null) {
} result = '<a href="' + url + data + '" target="_blank">Link</a>&nbsp;';
if (${allow_edit}) { }
result += '<a href="${url}/' + id + '/edit"><i class="fas fa-edit" aria-hidden="true"></i></a>&nbsp;' return result;
}
if (${allow_delete}) {
result += '<a href="${url}/' + id + '/delete"><i class="fas fa-trash" aria-hidden="true"></i></a>';
} }
return result;
} }
${tableid}Columns[co].width = "30pt"; else if (${tableid}Columns[co].data === "id" && ${tableid}Columns[co].action === true) {
${tableid}Columns[co].orderable = false; ${tableid}Columns[co].render = function (id) {
${tableid}Columns[co].className = "text-center"; let result = ""
${tableid}Columns[co].visible = true; if (${allow_view}) {
//columns[1].order = "order_asc"; result = '<a href="${url}/' + id + '/view"><i class="fas fa-eye" aria-hidden="true"></i></a>&nbsp;';
}
if (${allow_edit}) {
result += '<a href="${url}/' + id + '/edit"><i class="fas fa-edit" aria-hidden="true"></i></a>&nbsp;'
}
if (${allow_delete}) {
result += '<a href="${url}/' + id + '/delete"><i class="fas fa-trash" aria-hidden="true"></i></a>';
}
return result;
}
${tableid}Columns[co].width = "30pt";
${tableid}Columns[co].orderable = false;
${tableid}Columns[co].className = "text-center";
${tableid}Columns[co].visible = true;
//columns[1].order = "order_asc";
} }
} }
let ${tableid}Language = { let ${tableid}Language = {
"search": "Cari: ", "search": "Cari: ",
"paginate": { "paginate": {
...@@ -122,7 +130,7 @@ ...@@ -122,7 +130,7 @@
dom: '<"row"<"col-md-8"<"toolbar">Bl><"col-md-4"fr>>tip', dom: '<"row"<"col-md-8"<"toolbar">Bl><"col-md-4"fr>>tip',
processing: true, processing: true,
serverSide: ${server_side}, serverSide: ${server_side},
stateSave: false, stateSave: ${state_save},
scrollCollapse: true, scrollCollapse: true,
sort: ${sorts}, sort: ${sorts},
info: false, info: false,
...@@ -141,7 +149,8 @@ ...@@ -141,7 +149,8 @@
} }
if (!${server_side}) { if (!${server_side}) {
${tableid}Params.data = ${data}; ${tableid}Params.data = ${data};
} else { }
else {
${tableid}Params.ajax = o${tableid}Url; ${tableid}Params.ajax = o${tableid}Url;
} }
o${tableid} = $('#${tableid}').DataTable(${tableid}Params); o${tableid} = $('#${tableid}').DataTable(${tableid}Params);
......
...@@ -99,6 +99,13 @@ class DefaultModel(CommonModel): ...@@ -99,6 +99,13 @@ class DefaultModel(CommonModel):
return query return query
@classmethod @classmethod
def query_from(cls, db_session=DBSession, columns=None, filters=None):
query = db_session.query().select_from(cls)
for c in columns:
query = query.add_columns(c)
return query
@classmethod
def query_id(cls, row_id, db_session=DBSession): def query_id(cls, row_id, db_session=DBSession):
return cls.query(db_session).filter_by(id=row_id) return cls.query(db_session).filter_by(id=row_id)
...@@ -106,6 +113,11 @@ class DefaultModel(CommonModel): ...@@ -106,6 +113,11 @@ class DefaultModel(CommonModel):
def delete(cls, row_id, db_session=DBSession): def delete(cls, row_id, db_session=DBSession):
cls.query_id(row_id, db_session).delete() cls.query_id(row_id, db_session).delete()
@classmethod
def flush(cls, row, db_session=DBSession):
db_session.add(row)
db_session.flush()
class StandarModel(DefaultModel): class StandarModel(DefaultModel):
status = Column(SmallInteger, nullable=False, default=0) status = Column(SmallInteger, nullable=False, default=0)
......
...@@ -67,7 +67,7 @@ class UserResourcePermission(UserResourcePermissionMixin, Base): ...@@ -67,7 +67,7 @@ class UserResourcePermission(UserResourcePermissionMixin, Base):
pass pass
class User(UserMixin, BaseModel, CommonModel, Base): class User(UserMixin, BaseModel, DefaultModel, Base):
last_login_date = Column(DateTime(timezone=True), nullable=True) last_login_date = Column(DateTime(timezone=True), nullable=True)
registered_date = Column(DateTime(timezone=True), registered_date = Column(DateTime(timezone=True),
nullable=False, nullable=False,
...@@ -107,9 +107,9 @@ class User(UserMixin, BaseModel, CommonModel, Base): ...@@ -107,9 +107,9 @@ class User(UserMixin, BaseModel, CommonModel, Base):
def kode(self): def kode(self):
pass pass
@classmethod # @classmethod
def query(cls): # def query(cls):
return DBSession.query(cls) # return DBSession.query(cls)
@classmethod @classmethod
def get_by_email(cls, email): def get_by_email(cls, email):
...@@ -129,6 +129,11 @@ class User(UserMixin, BaseModel, CommonModel, Base): ...@@ -129,6 +129,11 @@ class User(UserMixin, BaseModel, CommonModel, Base):
def get_by_token(cls, token): def get_by_token(cls, token):
return DBSession.query(cls).filter_by(security_code=token) return DBSession.query(cls).filter_by(security_code=token)
@classmethod
def query_register(cls):
return cls.query_from(columns=[cls.email, cls.user_name, cls.registered_date,
cls.last_login_date])
# @classmethod # @classmethod
# def get_departemen_id(cls, user_id): # def get_departemen_id(cls, user_id):
...@@ -172,6 +177,9 @@ class ExternalIdentity(ExternalIdentityMixin, CommonModel, Base): ...@@ -172,6 +177,9 @@ class ExternalIdentity(ExternalIdentityMixin, CommonModel, Base):
return cls.query().filter_by(local_user_id=user.id) return cls.query().filter_by(local_user_id=user.id)
@classmethod @classmethod
@classmethod
def external(cls, user): def external(cls, user):
return cls.query_user(user).count()>0 return cls.query_user(user).count()>0
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!