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 1648 additions and 272 deletions
......@@ -15,14 +15,14 @@ Biasanya pada home directory::
$ ~/env/bin/pip install --upgrade pip setuptools
$ ~/env/bin/pip install wheel
##Instalasi
## Instalasi
###Production:
### Production:
$ ~/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
###Install Development::
### Install Development::
$ source ~/env/bin/activate
$ mkdir apps
$ cd apps
......@@ -30,11 +30,11 @@ Biasanya pada home directory::
$ env/bin/pip install -e base[dev]
$ cp ~/env/etc/test_opensipkd.tpl ~/env/etc/test_opensipkd.ini
##Sesuaikan konfigurasi
## Sesuaikan konfigurasi
Konfigurasi tergantung pada jenis instalasi ``test_opensipkd.ini`` atau
``live_opensipkd.ini``pada baris berikut ini::
###Database Koneksi:
### Database Koneksi:
[app:main]
sqlalchemy.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
sqlalchemy.url = postgresql://user:password@localhost:5432/db
script_location = opensipkd.base:alembic
###Login/Register:
### Login/Register:
[app:main]
captcha_files=
# static folder untuk image captcha
......@@ -65,7 +65,7 @@ Konfigurasi tergantung pada jenis instalasi ``test_opensipkd.ini`` atau
# diisi nama template login apabila akan menggunakan template yang berbeda
###Handling Log File:
### Handling Log File:
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
script_location = alembic
```
###Google Integrated dan Custom Register Form
### Google Integrated dan Custom Register Form
Aplikasi sudah bisa terintegrsi dengan google oauth2
Konfigurasi merupakan bagian dari "main"
......@@ -112,7 +112,7 @@ Konfigurasi merupakan bagian dari "main"
```
##Buat tabelnya::
## Buat tabelnya::
Perintah untuk membuat tabel
......
......@@ -40,7 +40,7 @@ from opensipkd.tools import (
from deform import ZPTRendererFactory, Form
from pkg_resources import resource_filename
from deform.widget import default_resource_registry
import os
from opensipkd.models.handlers import LogDBSession
......@@ -148,6 +148,7 @@ def add_global(event):
event['allow_register'] = allow_register
event['change_unit'] = change_unit
event['get_params'] = get_params
event['get_urls'] = get_urls
def get_params(params, alternate=None, settings=None):
......@@ -380,15 +381,18 @@ def json_rpc():
# if user is not None:
# 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):
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)
......@@ -419,8 +423,11 @@ partner_idcard_url = 'partner/idcard'
def main(global_config, **settings):
""" 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)
LogDBSession.configure(bind=engine)
Base.metadata.bind = engine
......@@ -467,7 +474,8 @@ def main(global_config, **settings):
config.add_request_method(thousand, 'thousand', 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_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,
'google_signin_client_id', reify=True)
config.add_request_method(google_signin_client_ids,
......
Generic single-database configuration.
alembic -c config -n section_name revision -m "notes "
\ 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>
*.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
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
# 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
{
"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
<!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
/*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
/*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
......@@ -477,7 +477,7 @@ div.col-md-6 {
padding: 7px !important;
}
.form-horizontal .checkbox, .form-horizontal .radio {
.form-horizontal .checkbox, .form-horizontal .radio, .form-horizontal .radio-inline{
padding: 0px;
}
......@@ -515,7 +515,7 @@ div.col-md-6 {
}
.checkbox label, .radio label {
.checkbox label, .radio label, .radio-inline {
font-size: 10px !important;
}
......
......@@ -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) {
// Strip all characters but numerical ones.
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.base import log
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
from pyramid.security import remember
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 .base_views import BaseView
......@@ -68,11 +68,11 @@ class Home(BaseView):
log.info(request.session.peek_flash())
if 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:
return HTTPFound(location=request.route_url(modules_default))
return HTTPFound(location=get_urls(request.route_url(modules_default)))
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")
home_tpl = get_params("home_tpl")
if home_tpl:
......@@ -87,7 +87,7 @@ class Home(BaseView):
@view_config(context=HTTPForbidden, renderer='templates/403.pt')
def http_forbidden(request):
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)
request.response.status = 403
......@@ -125,7 +125,7 @@ def view_password(request):
if not request.POST:
return dict(form=form.render())
if 'save' not in request.POST:
return HTTPFound(location=request.route_url('home'))
return HTTPFound(location=request._host)
schema.request = request
controls = request.POST.items()
try:
......@@ -135,7 +135,7 @@ def view_password(request):
UserService.set_password(request.user, c['new_password'])
DBSession.add(request.user)
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
from .company import company_widget
from .upload import AddSchema as UploadSchema
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_EDIT_FAILED = 'Edit departemen gagal'
......@@ -87,7 +87,7 @@ class AddSchema(colander.Schema):
size=60, min_length=3,
requirements=(("typeahead", None), ("deform", None),
{"js": "opensipkd.base:static/js/form/departemen.js"}),
values=f"{request.route_url('departemen')}/hon/act")
values=get_urls(f"{request.route_url('departemen')}/hon/act"))
if request.user.company_id:
self["company_id"].widget = widget.HiddenWidget()
self["company_id"].default = request.user.company_id
......
......@@ -7,7 +7,7 @@ from pyramid.view import (view_config, )
from sqlalchemy.orm import aliased
from ..views import ColumnDT, DataTables, BaseView
from .. import get_urls
_ = TranslationStringFactory("opensipkd")
SESS_ADD_FAILED = 'Tambah menu gagal'
......
......@@ -7,6 +7,7 @@ from opensipkd.base.views.kecamatan import kecamatan_widget
from opensipkd.base.views.provinsi import provinsi_widget
from opensipkd.tools import mem_tmp_store
from .. import get_urls
class NamaSchema(colander.Schema):
......@@ -132,8 +133,7 @@ class PartnerSchema(NamaSchema):
def after_bind(self, schema, kwargs):
request = kwargs["request"]
prefix = request.route_url("home")
self["provinsi_id"].slave_url=f"{prefix}/dati2/select/act?provinsi_id="
self["dati2_id"].slave_url=f"{prefix}/kecamatan/select/act?dati2_id="
prefix = get_urls(request.route_url("home"))
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["kecamatan_id"].slave_url = f"{prefix}/desa/select/act?kecamatan_id="
......@@ -47,6 +47,7 @@ from . import widget_os
from .base_views import need_captcha, get_url_captcha
from .user_login import regenerate_security_code, send_email_security_code
from ..views import BaseView
from .. import get_urls
_ = TranslationStringFactory('user')
......@@ -146,7 +147,7 @@ def _show_error(request, msg):
def 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():
......@@ -310,16 +311,16 @@ class Registrasi(BaseView):
def view_register(self):
if "g_state" in self.req.cookies:
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
reg_form = get_params("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)
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()
......@@ -365,7 +366,7 @@ class Registrasi(BaseView):
self.buttons = (btn_save, btn_cancel)
reg_form = get_params("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)
resp = super(Registrasi, self).view_edit()
if not resp:
......
<html tal:define="home request.route_url('home')[:-1];">
<html tal:define="home request._host;">
<body>
<div class="well">
<h3>Forbidden</h3>
......
<html tal:define="home request.route_url('home')[:-1];">
<html tal:define="home request._host;">
<body>
<div class="well">
<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>
<html lang="en" tal:define="home request.route_url('home');">
<html lang="en" tal:define="home request._host;">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" 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" />
<!-- 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.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-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-skins.min.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 -->
<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 -->
<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 -->
<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/typeahead.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}/deform_static/css/form.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/navbar-fixed-top.css" rel="stylesheet">
<!-- 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>
<style>
#content {
......@@ -58,12 +58,12 @@
<!-- <div class="navbar-collapse collapse" tal.condition="not request.user"> -->
<!-- <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 class="nav navbar-nav navbar-right" style="margin-right:0px;"> -->
<!-- <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> -->
<!-- </ul> -->
<!-- </div> -->
......@@ -81,21 +81,21 @@
<a href="#" class="dropdown-toggle txt-color-white" data-toggle="dropdown">Admin <b class="caret"></b></a>
<ul class="dropdown-menu">
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])">
<a href="${home}user">User</a>
<a href="${home}/user">User</a>
</li>
<li tal:condition="has_permission(request, ['user-view', 'user-edit'])">
<a href="${home}group">Group</a>
<a href="${home}/group">Group</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, '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, 'parameter')">
<a href="${home}parameter">Parameter</a></li>
<a href="${home}/parameter">Parameter</a></li>
<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')">
<a href="${home}partner">Partner</a></li>
<a href="${home}/partner">Partner</a></li>
<li tal:condition="has_permission(request, 'parameter')">
<a href="${home}parameter">Parameter</a></li>
<a href="${home}/parameter">Parameter</a></li>
</ul>
</li>
......@@ -104,15 +104,15 @@
['/password', '/recreate-api-key'] and 'active'">
<a href="#" class="dropdown-toggle txt-color-white" data-toggle="dropdown">My Account <b class="caret"></b></a>
<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}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}/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}/password">Ubah password</a></li>
<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
</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>
<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>
</li>
</ul>
......@@ -140,20 +140,20 @@
<!-- Bootstrap core JavaScript
================================================== -->
<!-- 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-ui-1.10.3.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">
// Change JQueryUI plugin names to fix name collision with Bootstrap.
$.widget.bridge('uitooltip', $.ui.tooltip);
$.widget.bridge('uibutton', $.ui.button);
</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/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}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}static/js/tools.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/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}/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}/static/js/tools.js"></script>
<metal:js define-slot="js_files"></metal:js>
<script metal:define-slot="scripts"></script>
......
<!DOCTYPE html>
<html lang="en-us"
tal:define="
home request.route_url('home')[:-1];
home request._host;
user_path ['user', 'user-add', 'user-edit', 'user-view', 'user-delete'];
user_ext_path ['user-ext', 'user-ext-view', 'user-ext-delete'];
group_path ['group', 'group-add', 'group-edit', 'group-view', 'group-delete'];
......
......@@ -40,7 +40,7 @@
<div class="col-sm-12 padding-thin">
<div class="box appname">
<div class="col-sm-3 padding-medium" align="center">
<img src="${home}${logo}" alt="">
<img src="${home}/${logo}" alt="">
</div>
<div class="col-sm-9 padding-high">
<span class="about-appname">${request.app_name}</span><br>
......@@ -53,14 +53,14 @@
<div class="col-sm-12 no-padding" align="center">
<div tal:repeat="modul modules" class="col-sm-3 col-xs-6 module padding-thin">
<a tal:condition="modul.find('://')<0"
href="${home}${modul}" icon="${modul.replace('/','_')}" class="box">
<img alt="" class="icon-modul" src="${home}static/icon/${modul.replace('/','_')}.png">
href="${home}/${modul}" icon="${modul.replace('/','_')}" class="box">
<img alt="" class="icon-modul" src="${home}/static/icon/${modul.replace('/','_')}.png">
<span>${modules[modul]}</span>
</a>
<a tal:condition="modul.find('://')>-1" target="_blank"
href="${modul}" class="box">
<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>
</a>
</div>
......@@ -74,21 +74,21 @@
<div class="modal-content">
<div class="modal-body">
<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>
Aplikasi ini dibangun dengan menggunakan platform Open Source yang terdiri dari :
<div class="clearfix" style="margin-top:20px"></div>
<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/pyramid.png" alt=""> <a href="http://pylonsproject.org/">Pyramid</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>
<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/deform/">Deform</a>
</div>
<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/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/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/postgree.png" alt=""> <a href="http://postgresql.org">Postgres SQL</a>
</div>
<div class="clearfix"></div>
</div>
......@@ -101,11 +101,11 @@ $( ".module a" ).each(function() {
var modul = $(this);
var modulenm = modul.attr('icon');
$.ajax({
url:'${home}static/icon/'+ modulenm+'.png',
url:'${home}/static/icon/'+ modulenm+'.png',
type:'HEAD',
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"
tal:define="
home request.route_url('home');">
home request._host;">
<div metal:fill-slot="content">
<div class="jarviswidget jarviswidget-color-blueLight"> <!-- jarviswidget -->
<div tal:content="structure table"></div>
......
<!DOCTYPE html>
<html lang="en"
tal:define="home request.route_url('home')[:-1];">
tal:define="home request._host;">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
......
<!DOCTYPE html>
<html lang="en" tal:define="home request.route_url('home');">
<html lang="en" tal:define="home request._host;">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
......@@ -10,22 +10,22 @@
<meta tal:condition="request.google_signin_client_id"
name="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>
<!-- 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/font-awesome.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">
<!-- 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.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="${home}static/v3/css/smartadmin-skins.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-skins.min.css">
<!-- 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" href="${home}static/css/home.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">
</head>
......@@ -54,7 +54,7 @@
tal:repeat="message request.session.pop_flash('error')">${message}</div>
</div>
<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;"/>
</div>
<div class="clearfix"></div>
......@@ -83,9 +83,9 @@
<!-- Bootstrap core JavaScript
================================================== -->
<!-- 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/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/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/deform.js"></script>
<!--?<script tal:condition="request.google_signin_client_id"-->
<!--? src="https://apis.google.com/js/platform.js" async defer></script>-->
<!--?<script tal:condition="request.google_signin_client_id">-->
......
<!DOCTYPE html>
<html lang="en"
tal:define="
home request.route_url('home');">
home request._host;">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" 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"/>
<link rel="stylesheet" type="text/css"
href="${home}static/v3/css/bootstrap.min.css">
href="${home}/static/v3/css/bootstrap.min.css">
</link>
<link rel="stylesheet" type="text/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}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/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/css/theme.css">
<link rel="stylesheet" type="text/css" href="${home}static/css/navbar-fixed-top.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}/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/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/css/theme.css">
<link rel="stylesheet" type="text/css" href="${home}/static/css/navbar-fixed-top.css">
<link metal:define-slot="link"/>
<style>
html{ height:100%;}
......@@ -66,7 +66,7 @@ var gmapKey = '${request.gmap_key}';
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="${home}login" class="button">Masuk</a>
<a href="${home}/login" class="button">Masuk</a>
</li>
</ul>
</div>
......@@ -83,30 +83,30 @@ var gmapKey = '${request.gmap_key}';
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Admin <b class="caret"></b></a>
<ul class="dropdown-menu">
<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')">
<a href="${home}group">Group</a></li>
<a href="${home}/group">Group</a></li>
<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')">
<a href="${home}routes">Routes</a></li>
<a href="${home}/routes">Routes</a></li>
<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')">
<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')">
<a href="${home}user/ws">User Web Service</a></li>
<a href="${home}/user/ws">User Web Service</a></li>
</ul>
</li>
<!-- 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>
<ul class="dropdown-menu">
<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}/logout">${request.user.nice_username()} Logout</a></li>
<li><a href="${home}/password">Ubah password</a></li>
<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>
</li>
</ul>
......@@ -134,16 +134,16 @@ var gmapKey = '${request.gmap_key}';
</div>
</div>
<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"
src="${home}static/v3/js/bootstrap/bootstrap.min.js"></script>
src="${home}/static/v3/js/bootstrap/bootstrap.min.js"></script>
<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 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/ol3-layerswitcher.js"></script>
<script type="text/javascript" src="${home}/static_map/lib/ol4/ext/ol-geocoder.js"></script>
<script type="text/javascript">
if (ol.Map.prototype.getLayer === undefined) {
ol.Map.prototype.getLayer = function (id) {
......
<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">
<script tal:condition="${captcha}">
......
......@@ -13,12 +13,12 @@ from opensipkd.tools import (
)
from pyramid.httpexceptions import HTTPFound
from pyramid.view import view_config
from .. import get_urls
# from unggah import DbUpload
def route_list(request, 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):
self.edit_schema = EditSchema
self.add_schema = AddSchema
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):
status_list = (
......@@ -76,38 +80,38 @@ class Views(BaseView):
@view_config(
route_name='user-act', renderer='json', permission='user-view')
def view_act(self):
url_dict = self.req.matchdict
if url_dict['act'] == 'csv':
query = query_register()
row = query.first()
header = row.keys()
rows = [list(item) for item in query.all()]
filename = 'user.csv'
value = {
'header': header,
'rows': rows,
}
return csv_response(self.req, value, filename)
elif url_dict['act'] == 'pdf':
query = query_register()
import opensipkd.base
base_path = os.path.dirname(opensipkd.base.__file__)
path = os.path.join(base_path, 'reports')
rml_row = open_rml_row(path + '/user.row.rml')
rows = [rml_row.format(user_name=r.user_name, email=r.email,
registered_date=r.registered_date) for r in
query.all()]
pdf, filename = open_rml_pdf(path + '/user.rml', rows=rows,
company=self.req.company,
departement=self.req.departement,
address=self.req.address,
base_path=base_path)
filename = os.path.basename(filename)
resp = pdf_response(self.req, pdf, filename)
if resp.content_length < 10:
resp.content_length = len(resp.body)
return resp
# url_dict = self.req.matchdict
# if url_dict['act'] == 'csv':
# query = query_register()
# row = query.first()
# header = row.keys()
# rows = [list(item) for item in query.all()]
# filename = 'user.csv'
# value = {
# 'header': header,
# 'rows': rows,
# }
# return csv_response(self.req, value, filename)
#
# elif url_dict['act'] == 'pdf':
# query = query_register()
# import opensipkd.base
# base_path = os.path.dirname(opensipkd.base.__file__)
# path = os.path.join(base_path, 'reports')
# rml_row = open_rml_row(path + '/user.row.rml')
# rows = [rml_row.format(user_name=r.user_name, email=r.email,
# registered_date=r.registered_date) for r in
# query.all()]
# pdf, filename = open_rml_pdf(path + '/user.rml', rows=rows,
# company=self.req.company,
# departement=self.req.departement,
# address=self.req.address,
# base_path=base_path)
# filename = os.path.basename(filename)
# resp = pdf_response(self.req, pdf, filename)
# if resp.content_length < 10:
# resp.content_length = len(resp.body)
# return resp
return super(Views, self).view_act()
......@@ -347,7 +351,7 @@ class AddSchema(colander.Schema):
class EditSchema(AddSchema):
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():
......@@ -387,3 +391,33 @@ def query_register():
"DD-MM-YYYY").label(
"registered_date")).order_by(
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 (
UserGroup, )
from datatables import ColumnDT, DataTables
from .. import get_urls
SESS_ADD_FAILED = 'Tambah user gagal'
SESS_EDIT_FAILED = 'Edit user gagal'
......@@ -160,7 +160,7 @@ def save_request(values, request, row=None):
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):
......@@ -186,7 +186,7 @@ def view_add(request):
c = form.validate(controls)
except ValidationFailure as e:
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)
return route_list(request)
elif SESS_ADD_FAILED in request.session:
......@@ -225,8 +225,8 @@ def view_edit(request):
c = form.validate(controls)
except ValidationFailure as e:
request.session[SESS_EDIT_FAILED] = e.render()
return HTTPFound(location=request.route_url('user-group-edit',
id=row.id))
return HTTPFound(location=get_urls(request.route_url('user-group-edit',
id=row.id)))
save_request(dict(controls), request, row)
return route_list(request)
elif SESS_EDIT_FAILED in request.session:
......
......@@ -44,7 +44,7 @@ from pyramid_mailer.message import Message
from opensipkd.tools.buttons import btn_cancel
from opensipkd.tools.form_api import formfield2dict
from .. import get_urls
log = __import__("logging").getLogger(__name__)
......@@ -168,11 +168,11 @@ class ViewLogin(BaseView):
next_url = request.params.get('next', request.referrer)
login_tpl = get_params('login_tpl', 'templates/login.pt')
if not next_url:
next_url = request.route_url('home')
next_url = get_urls(request.route_url('home'))
if request.authenticated_userid: # (request):
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)
form = Form(schema, buttons=('login',))
......@@ -187,7 +187,7 @@ class ViewLogin(BaseView):
msg = 'Login gagal'
set_user_log(msg, request, log, identity)
request.session.flash(msg, 'error')
return HTTPFound(location=request.route_url('login'))
return HTTPFound(location=get_urls(request.route_url('login')))
values = dict(c)
# start cek external module
......@@ -206,19 +206,19 @@ class ViewLogin(BaseView):
except Exception as e:
log.warn(str(e))
request.session.flash(str(e), "error")
return HTTPFound(location=request.route_url('login'))
return HTTPFound(location=get_urls(request.route_url('login')))
else:
login = LoginUser(self.req)
if not login.login(values, user):
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 redirect_login(request, user)
elif 'register' in request.POST:
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:
r = dict(form=request.session['login failed'])
......@@ -236,13 +236,13 @@ class ViewLogin(BaseView):
login_tpl, dict(
form=form.render(),
message=message,
url=request.route_url('login'),
url=get_urls(request.route_url('login')),
next_url=next_url,
login=login, ),
request=request)
except Oauth2UserExc as e:
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:
return redirect_login(request, user)
......@@ -250,7 +250,7 @@ class ViewLogin(BaseView):
if login_tpl == 'templates/login.pt':
return dict(form=form.render(),
message=message,
url=request.route_url('login'),
url=get_urls(request.route_url('login')),
next_url=next_url,
login=login, )
......@@ -259,7 +259,7 @@ class ViewLogin(BaseView):
request=request,
value=dict(form=form.render(),
message=message,
url=request.route_url('login'),
url=get_urls(request.route_url('login')),
next_url=next_url,
login=login, ),
)
......@@ -272,7 +272,7 @@ def redirect_login(request, user):
next_url = request.params.get('next')
if not next_url and request.matched_route.name == 'login':
url = get_params('modules_default', 'home')
return HTTPFound(location=request.route_url(url),
return HTTPFound(location=get_urls(request.route_url(url)),
headers=headers)
return HTTPFound(location=next_url, headers=headers)
......@@ -299,8 +299,8 @@ class Logout(BaseView):
form = self.get_form(LogoutSchema, buttons=(btn_cancel, btn_logout))
if 'cancel' in request.POST or "home" in request.POST:
log.info(request.route_url('home'))
return HTTPFound(location=f"{request.route_url('home')}", )
log.info(get_urls(request.route_url('home')))
return HTTPFound(location=get_urls(f"{request.route_url('home')}", ))
elif "logout" in request.POST:
form = self.get_form(LogoutSchema, buttons=(btn_home,))
......@@ -343,7 +343,7 @@ def change_password_validator(form, value):
def view_change_password(request):
if request.authenticated_userid:
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)
btn_save = Button('save', _('Simpan'))
......@@ -353,7 +353,7 @@ def view_change_password(request):
if not request.POST:
return dict(form=form.render())
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()
try:
c = form.validate(items)
......@@ -365,7 +365,7 @@ def view_change_password(request):
if not user or \
create_now() - user.security_code_date > one_hour:
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
UserService.set_password(user, c['new_password'])
......@@ -373,7 +373,7 @@ def view_change_password(request):
headers = get_login_headers(request, user)
request.session.flash('Password baru Anda sudah disimpan.')
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):
d = dict(api_key=request.user.api_key)
return dict(form=form.render(appstruct=d))
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()
DBSession.add(request.user)
msg = 'API Key Anda yang baru {}'.format(api_key)
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):
def security_code_age(user):
now = create_now()
if user.security_code_date:
return now - user.security_code_date
return timedelta(minutes=1)
def send_email_security_code(
......@@ -508,7 +510,7 @@ def regenerate_security_code(user, hour=1.0):
renderer='templates/reset-password.pt')
def view_reset_password(request):
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'))
schema = ResetPassword(validator=reset_password_validator)
......@@ -530,7 +532,7 @@ def view_reset_password(request):
send_email_security_code(
request, user, remain, 'Reset password', 'reset-password-body',
'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()
return resp
......
......@@ -3,8 +3,12 @@ import logging
from deform.widget import (
SchemaType,
DateInputWidget as DeformDateInputWidget)
from colander import null, Invalid
DateInputWidget as DeformDateInputWidget,
default_resources, ResourceRegistry, default_resource_registry, _StrippedString, Widget)
from colander import null, Invalid, SchemaNode, Mapping
_logging = logging.getLogger(__name__)
class _FieldStorage(SchemaType):
def deserialize(self, node, cstruct):
......@@ -16,52 +20,48 @@ class _FieldStorage(SchemaType):
return cstruct
class DateInputWidget(DeformDateInputWidget):
"""
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``.
"""
default_options = (
("format", "yyyy-mm-dd"),
("selectMonths", True),
("selectYears", True),
("formatSubmit", "yyyy-mm-dd"),
)
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
)
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):
logging.debug(f"widget: {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"]
# default_resources = {
# "jquery.form": {None: {"js": "deform:static/scripts/jquery.form-3.09.js"}},
# "jquery.maskedinput": {
# None: {"js": "deform:static/scripts/jquery.maskedinput-1.3.1.min.js"}
# },
# "jquery.maskMoney": {
# None: {"js": "deform:static/scripts/jquery.maskMoney-3.1.1.min.js"}
# },
# "deform": {
# None: {
# "js": (
# "deform:static/scripts/jquery.form-3.09.js",
# "deform:static/scripts/deform.js",
# )
# }
# },
# "typeahead": {
# None: {
# "js": "deform:static/scripts/typeahead.min.js",
# "css": "deform:static/css/typeahead.css",
# }
# },
# "modernizr": {
# None: {
# "js": "deform:static/scripts/modernizr.custom.input-types-and-atts.js" # noQA
# }
# },
# "pickadate": {
# None: {
# "js": (
# "static/pickadate/lib/picker.js",
# "static/pickadate/lib/picker.date.js",
# "static/pickadate/lib/picker.time.js",
# "static/pickadate/lib/legacy.js",
# ),
# "css": (
# "static/pickadate/lib/themes/default.css",
# "static/pickadate/lib/themes/default.date.css",
# "static/pickadate/lib/themes/default.time.css",
# ),
# }
# },
# }
#
# default_resource_registry = ResourceRegistry()
import json
import logging
from colander import SchemaNode, null, Mapping, Invalid, text_, string_types
from deform.widget import Widget, _StrippedString, Select2Widget
from colander import SchemaNode, null, Mapping, Invalid, string_types
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__)
......@@ -46,7 +51,7 @@ class DokumenWidget(Widget):
try:
validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc))
raise Invalid(field.schema, f"Invalid pstruct: {exc}")
jenis = validated["jenis"]
year = validated["year"]
bundle = validated["bundle"]
......@@ -101,7 +106,7 @@ class FormulirWidget(Widget):
try:
validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc))
raise Invalid(field.schema, f"Invalid pstruct: {exc}")
year = validated["year"]
bundle = validated["bundle"]
seq = validated["seq"]
......@@ -154,7 +159,7 @@ class BlokKavNoWidget(Widget):
try:
validated = self._pstruct_schema.deserialize(pstruct)
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"]
rt = validated["rt"]
rw = validated["rw"]
......@@ -187,6 +192,8 @@ class Select2MsWidget(Select2Widget):
"""
url = ""
slave = ""
template = "select2_ms.pt"
......@@ -221,7 +228,7 @@ class QtyWidget(Widget):
try:
validated = self._pstruct_schema.deserialize(pstruct)
except Invalid as exc:
raise Invalid(field.schema, text_("Invalid pstruct: %s" % exc))
raise Invalid(field.schema, f"Invalid pstruct: {exc}")
qty = validated["qty"]
measure = validated["measure"]
......@@ -493,3 +500,206 @@ class LeafMapWidget(Widget):
if not pstruct:
return null
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 @@
oid oid|field.oid;
true_val true_val|field.widget.true_val;"
i18n:domain="deform">
<p class="deform-readonly-true form-control-static"
<p class="deform-readonly-true"
id="${oid}"
tal:condition="cstruct == true_val"
i18n:translate="">True</p>
<p class="deform-readonly-false form-control-static"
i18n:translate=""><i class="fas fa-check-square" aria-hidden="true"></i></p>
<p class="deform-readonly-false"
id="${oid}"
tal:condition="cstruct != true_val"
i18n:translate="">False</p>
i18n:translate=""><i class="fas fa-window-close" aria-hidden="true"></i></p>
</div>
......@@ -55,10 +55,10 @@
<script type="text/javascript">
deform.addCallback(
'${field.oid}',
function(oid) {
function (oid) {
$('#' + oid).select2({
containerCssClass: 'form-control',
placeholder: "${str(field.widget.placeholder).replace('"','\\"')|""}" || undefined,
placeholder: "${str(field.widget.placeholder).replace('"','\\"')|""}" || undefined,
allowClear: "${hasattr(field.widget, 'placeholder')}",
tags: ${str(getattr(field.widget, 'tags', 'undefined')).lower()}
});
......@@ -68,7 +68,7 @@
<script type="text/javascript" tal:condition="url and slave">
deform.addCallback(
'${field.oid}',
function(oid) {
function (oid) {
$('#' + oid).change(function () {
$("#${slave}").val("");
$("#${slave}").empty();
......
<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
......@@ -109,6 +109,7 @@ class DeTable(field.Field):
paginates='true',
params="",
server_side='true',
state_save=True,
data=[],
allow_edit=True,
allow_delete=True,
......@@ -246,6 +247,7 @@ class DeTable(field.Field):
self.sorts = sorts
self.paginates = paginates
self.filters = filters
self.state_save = json.dumps(state_save)
class Button(object):
......
......@@ -19,6 +19,7 @@
allow_edit allow_edit|field.allow_edit;
allow_delete allow_delete|field.allow_delete;
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|{};"
i18n:domain="detable"
......@@ -68,6 +69,10 @@
return 'Archived';
}
function render_checklist(value) {
return '<input type="checkbox" checked="'+{value}+'"></input>';
}
for (let co in ${tableid}Columns) {
if (${tableid}Columns[co].checkbox === true) {
${tableid}Columns[co].className = "text-center";
......@@ -77,7 +82,8 @@
return render_checkbox(true);
} else return render_checkbox(false);
}
} else if (${tableid}Columns[co].hasOwnProperty("url")) {
}
else if (${tableid}Columns[co].hasOwnProperty("url")) {
let url = ${tableid}Columns[co].url;
${tableid}Columns[co].render = function (data) {
let result = "No Data"
......@@ -86,7 +92,8 @@
}
return result;
}
} else if (${tableid}Columns[co].data === "id" && ${tableid}Columns[co].action === true) {
}
else if (${tableid}Columns[co].data === "id" && ${tableid}Columns[co].action === true) {
${tableid}Columns[co].render = function (id) {
let result = ""
if (${allow_view}) {
......@@ -108,6 +115,7 @@
}
}
let ${tableid}Language = {
"search": "Cari: ",
"paginate": {
......@@ -122,7 +130,7 @@
dom: '<"row"<"col-md-8"<"toolbar">Bl><"col-md-4"fr>>tip',
processing: true,
serverSide: ${server_side},
stateSave: false,
stateSave: ${state_save},
scrollCollapse: true,
sort: ${sorts},
info: false,
......@@ -141,7 +149,8 @@
}
if (!${server_side}) {
${tableid}Params.data = ${data};
} else {
}
else {
${tableid}Params.ajax = o${tableid}Url;
}
o${tableid} = $('#${tableid}').DataTable(${tableid}Params);
......
......@@ -99,6 +99,13 @@ class DefaultModel(CommonModel):
return query
@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):
return cls.query(db_session).filter_by(id=row_id)
......@@ -106,6 +113,11 @@ class DefaultModel(CommonModel):
def delete(cls, row_id, db_session=DBSession):
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):
status = Column(SmallInteger, nullable=False, default=0)
......
......@@ -67,7 +67,7 @@ class UserResourcePermission(UserResourcePermissionMixin, Base):
pass
class User(UserMixin, BaseModel, CommonModel, Base):
class User(UserMixin, BaseModel, DefaultModel, Base):
last_login_date = Column(DateTime(timezone=True), nullable=True)
registered_date = Column(DateTime(timezone=True),
nullable=False,
......@@ -107,9 +107,9 @@ class User(UserMixin, BaseModel, CommonModel, Base):
def kode(self):
pass
@classmethod
def query(cls):
return DBSession.query(cls)
# @classmethod
# def query(cls):
# return DBSession.query(cls)
@classmethod
def get_by_email(cls, email):
......@@ -129,6 +129,11 @@ class User(UserMixin, BaseModel, CommonModel, Base):
def get_by_token(cls, 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
# def get_departemen_id(cls, user_id):
......@@ -172,6 +177,9 @@ class ExternalIdentity(ExternalIdentityMixin, CommonModel, Base):
return cls.query().filter_by(local_user_id=user.id)
@classmethod
@classmethod
def external(cls, user):
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!