handling of purchases, and payments

legacy
Steve L. Nyemba 8 years ago
parent 13d0b5e805
commit 4654641c5b

@ -0,0 +1,23 @@
cffi==1.8.3
click==6.6
couchdbkit==0.6.5
cryptography==1.5.3
enum34==1.1.6
Flask==0.11.1
http-parser==0.8.3
idna==2.1
ipaddress==1.0.17
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
ndg-httpsclient==0.4.2
pyasn1==0.1.9
pycparser==2.17
pyOpenSSL==16.2.0
requests==2.11.1
restkit==4.2.2
six==1.10.0
socketpool==0.5.3
stripe==1.41.1
Werkzeug==0.11.11
xmljson==0.1.7

@ -0,0 +1,157 @@
"""
This class is designed to handle Clients
"""
import stripe
from couchdbkit import Server, Document
import json
from sets import Set
class User:
def __init__(self,db,stripe=None,stripeToken=None) :
self.db = db
self.stripe = stripe;
self.stripeToken= stripeToken
self.user = None
"""
This function creates a stripe customer, and saves a copy with us for internal use
"""
def init (self,uid,plans=None):
customer = {}
# self.hasPlan(uid,plan)
if self.db.doc_exist(uid) == False and plans and stripe :
#
# First time customer, register them and sign them up for the first plan
#
customer['source'] = str(self.stripeToken)
customer = self.stripe.Customer.create(
source=self.stripeToken,
email=uid
) ;
id = customer['id']
subscriptions = self.subscribe(id,plans)
if uid and self.db.doc_exist(uid) == False:
info = {'id':id,'created':customer.created}
info['_id'] = uid.strip();
info['subscriptions'] = subscriptions
r = self.db.save_doc(info) ;
if r['ok'] :
self.user = info;
else:
#
# @TODO: update 4if the a plan was provided
self.user = self.db.get(uid) ;
r = stripe.Customer.retrieve(self.user['id'])
self.user['subscriptions'] = r.subscriptions.data
self.db.save_doc(self.user)
def subscriptions(self):
return self.user['subscriptions']
"""
This function subscribes a customer to n-plans
@pre isinstance(plans,list)
"""
def subscribe(self,id,plans):
r = []
for plan in plans:
x = self.stripe.Subscription.create(
customer=id,
plan=plan['id']
) ;
r.append(x)
return r
"""
This function will save card information
"""
def save_card(self,uid,token):
user = self.db.get(uid)
if 'sources' not in user or (token not in user['sources']):
#
# In this case we don't have a card
#
id = user['id']
customer = stripe.Customer.retrieve(id)
card = customer.sources.create(source = token)
if 'sources' not in user:
user['sources'] = []
user['sources'].append(card['id'])
self.db.save_doc(user) ;
self.user = user
"""
This function creates an invoice
@pre : an item with amount > 0 and status past_due
"""
def get_invoices(self,uid):
info = self.db.get(uid)
id = info['id']
return stripe.Invoice.list(customer=id)
"""
This function will clear a particular invoice (hopefully). No partial payments should be accepted
@pre : card,invoice
"""
def charge(self,uid,amount):
info = self.db.get(uid)
id = info['id']
uid = info['_id']
invoices= self.get_invoices(uid)
index = -1
for invoice in invoices :
if invoice.paid == False and invoice.amount_due == amount and amount > 0:
index = info['invoices'].index(ii)
invoice.pay()
del info['invoices'][index]
self.db.save_doc(info)
break
pass;
"""
This function is designed to determine if the user exists or not
We will check the couchdb and the stripe backend
"""
def exists(self,uid):
return self.db.doc_exist(uid)
# return self.user is not None ;
"""
This function will store the user within our system
"""
def attach(self,attachment,name,mime):
self.db.put_attachment(self.user,attachment,name,mime) ;
def save(self,uid=None):
if self.exists() == False:
self.init(uid) ;
else:
#perform an update
pass
"""
This function updates/creates a user remotely
@pre:
"""
def publish(self,info={}):
# We need to figure out whether to create or update;
#
if self.user is not None and info is not None:
customer = self.stripe.Customer.retrieve(self.user['id']) ;
customer.metadata = info ;
customer.save() ;
#f = open('config.json')
#conf = json.loads(f.read())
#f.close()
#server = Server(uri=conf['couchdb']['uri']) ;
#db = server.get_db(conf['couchdb']['db']) ;
#print db.doc_exist('steve@gmail.com')
#doc = db.get('steve@gmail.com')
#doc['type'] = 'business'
#db.save_doc(doc) ;

@ -0,0 +1,63 @@
<style>
body{
font-family:sans-serif;
font-size:14px;
font-weight:lighter;
}
.caption {
font-size:22px;
}
.left { float:left}
.small { font-family:verdana; font-size:11px;}
table { border:1px solid #CAD5E0;
border-radius:8px;
-webkit-border-radius:8px;
padding:4px;
width:55%;
margin-top:10%;
}
tr {font-family:sans-serif; font-size:14px;}
td {padding:4px; font-weight:lighter}
</style>
<body>
<div>
</div>
<br>
<div id="grid">
<table align="center">
<tr>
<td colspan="2">
<div align="left" class="caption">
<img src="static/img/logo.png" style="width:48px" class="left"> The Phi Technology LLC</div>
<div class="small">3-launchpad Cloud Music Player</div>
</td>
<td class="small" valign="middle">
<div>Call : 615-866-0454</div>
<div>Email: support@the-phi.com</div>
</td>
</tr>
<tr style="background-color:#f3f3f3">
<td>Service</td>
<td>Price /mo</td>
<td>Status</td>
</tr>
{% for item in plans %}
<tr class="default">
<td> {{item.feature}} </td>
<td> {{item.price}} </td>
<td> {{item.status}} </td>
</tr>
{% endfor %}
<tr>
<td align="right">Total Amount Due</td>
<td align="left" colspan="2">$ {{total_amount }}</td>
</tr>
</table>
</div>
</body>

@ -0,0 +1,197 @@
from __future__ import division
from flask import Flask, request, session, render_template,Response
import Domain
from couchdbkit import Server, Document
import stripe
import json
from StringIO import StringIO
import re
import os
PORT = 8100 ;
path = os.environ['CONFIG']
f = open(path)
CONFIG = json.loads(f.read())
stripe_keys = {
'secret_key': CONFIG['stripe']['secret'].strip(),
'publishable_key': CONFIG['stripe']['pub'].strip()
}
stripe.api_key = stripe_keys['secret_key'].strip()
app = Flask(__name__)
"""
This function will attempt to create an account for a user if the user does NOT exist
Then Setup the stage for initialization of {signup for, user-account}
"""
COUCHDB = Server(uri=CONFIG['couchdb']['uri']) ;
@app.route('/init',methods=['POST'])
def init():
DB = COUCHDB.get_db(CONFIG['couchdb']['db']) ;
out_resp = '0'
if 'User-Info' in request.headers:
stream = request.headers.get('User-Info') ;
user = json.loads(stream) ;
session['user-info'] = user ;
#
# We should create the user in couchdb
uid = user['uid'] ;
session['uid'] = uid
handler = Domain.User(DB,stripe) ;
"""
registering the user with us and making sure we can keep track of her basic operations & access to features
At this point this is just a user i.e a consumer (not store owner), we will tally track on the type of user later on
"""
if handler.exists(uid) == False:
#
# We need to subscribe the user to the freemium services if any at all
# Subscribing to a freemium plan hopefully this enables basic features of the application
#
free = []
paid = []
plans = [plan for plan in stripe.Plan.list().data if plan.amount == 0 ]
handler.init(uid,plans) ;
out_resp = session['user-info']
elif 'subscriptions' not in session:
#
# We have the user we should return the user's information
#
handler.init(uid)
out_resp = handler.subscriptions()
#
# updating user-info with more information ...
#
session['user-info'] = handler.user;
out_resp = CONFIG['stripe']['pub'].strip()
# return '1'
elif 'user-info' in session:
out_resp = CONFIG['stripe']['pub'].strip()
return out_resp
"""
This function defines if a given user is a customer or not
We should be able to tell by how we create customers
"""
@app.route('/checkout',methods=['GET'])
def is_customer ():
bill = {"amount":0,"count":0}
key = ""
if 'user-plans' in session :
plans = session['user-plans'] ;
amount = [plan['amount'] for plan in plans if plan['amount'] > 0]
if len(amount) > 0:
key = CONFIG['stripe']['pub'].strip()
bill['count'] = len(amount)
bill['amount']= sum(amount)
return render_template('checkout.html',bill=bill,key=key)
"""
This function is intended to performa an actual payment
"""
@app.route('/pay',methods=['POST'])
def pay():
token = request.form['stripeToken']
uid = request.form['stripeEmail']
tokenType = request.form['stripeTokenType']
DB = COUCHDB.get_db(CONFIG['couchdb']['db']) ;
handler = Domain.User(DB,stripe) ;
#
# Let's insure the preconditions are met i.e
# card,invoice
info = session['user-info']
uid = info['_id']
if 'sources' not in info or token not in info['sources']:
#
# Let's create the card
handler.save_card(uid,token)
#
# Let's create a charge here ...
plans = session['user-plans']
amount=[item['price'] for item in plans if item['status'] == 'past_due' ]
if len(amount) == 0:
amount = 0
else:
amount = sum(amount)
handler.charge(uid,amount)
session['user-info'] = handler.user
return ('',204)
#return render_template("bill.html",plans=plans, total_amount=amount)
@app.route('/bill',methods=['GET'])
def bill():
return render_template('bill.html')
@app.route('/buy',methods=['POST'])
def buy():
id = request.form['id'] ;
if id in ['subscribe','now']:
email = request.form['stripeEmail']
token = request.form['stripeToken']
user = Domain.User(DB,stripe,token) ;
user.init(email) ;
if user.exists() :
print "Update with anything if need be"
pass
else:
#
# Create the user with the associated plan/or payment method
#
user.save() ;
user.publish()
else:
pass
return "0"
"""
This function provides general information about service plans
@TODO: provide filtering criteria
"""
@app.route('/plans',methods=['GET'])
def plans():
plans = stripe.Plan.list().data
plans = [{"id":item.id,"price":item.amount/100,"feature":item.metadata['info'],"trial":item.trial_period_days} for item in plans if re.match('cloudplayer',item.id)]
if 'uid' in request.headers and request.headers['uid'] != '':
uid = request.headers['uid']
DB = COUCHDB.get_db(CONFIG['couchdb']['db']) ;
handler = Domain.User(DB)
handler.init(uid)
myplans = [{"id":item.plan.id,"price":item.plan.amount/100,"feature":item.plan.metadata['info'],"status":item.status} for item in handler.subscriptions()]
keys = [plan['id'] for plan in myplans]
plans = [plan for plan in plans if plan['price'] > 0 and plan['id'] not in keys]
plans = {'myplans':myplans,"plans":plans}
session['user-plans'] = myplans
plans = json.dumps(plans)
return plans
"""
This function subscribes a user to a given plan(s)
If the plan is new, then we do NOT need a credit card info
"""
@app.route('/subscribe',methods=['POST'])
def subscribe():
plans = [{"id":id} for id in request.get_json(silent=True)]
user = session['user-info']
DB = COUCHDB.get_db(CONFIG['couchdb']['db']) ;
handler = Domain.User(DB,stripe)
r = handler.subscribe(user['id'],plans)
return json.dumps(r)
app.debug = True ;
app.secret_key = '360-8y-[0v@t10n]+kr81v17y'
app.run(port=PORT,threaded=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

@ -0,0 +1,46 @@
(function(jsGrid) {
jsGrid.locales.de = {
grid: {
noDataContent: "Die Daten konnten nicht gefunden werden",
deleteConfirm: "Möchten Sie die Daten unwiederruflich löschen?",
pagerFormat: "Seiten: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} von {pageCount}",
pagePrevText: "<",
pageNextText: ">",
pageFirstText: "<<",
pageLastText: ">>",
loadMessage: "Bitte warten...",
invalidMessage: "Ihre Eingabe ist nicht zulässig!"
},
loadIndicator: {
message: "Lädt..."
},
fields: {
control: {
searchModeButtonTooltip: "Suche",
insertModeButtonTooltip: "Eintrag hinzufügen",
editButtonTooltip: "Bearbeiten",
deleteButtonTooltip: "Löschen",
searchButtonTooltip: "Eintrag finden",
clearFilterButtonTooltip: "Filter zurücksetzen",
insertButtonTooltip: "Hinzufügen",
updateButtonTooltip: "Speichern",
cancelEditButtonTooltip: "Abbrechen"
}
},
validators: {
required: { message: "Dies ist ein Pflichtfeld" },
rangeLength: { message: "Die Länge der Eingabe liegt außerhalb des zulässigen Bereichs" },
minLength: { message: "Die Eingabe ist zu kurz" },
maxLength: { message: "Die Eingabe ist zu lang" },
pattern: { message: "Die Eingabe entspricht nicht dem gewünschten Muster" },
range: { message: "Der eingegebene Wert liegt außerhalb des zulässigen Bereichs" },
min: { message: "Der eingegebene Wert ist zu niedrig" },
max: { message: "Der eingegebene Wert ist zu hoch" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,46 @@
(function(jsGrid) {
jsGrid.locales.es = {
grid: {
noDataContent: "No encontrado",
deleteConfirm: "¿Está seguro?",
pagerFormat: "Paginas: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} de {pageCount}",
pagePrevText: "Anterior",
pageNextText: "Siguiente",
pageFirstText: "Primero",
pageLastText: "Ultimo",
loadMessage: "Por favor, espere...",
invalidMessage: "¡Datos no válidos!"
},
loadIndicator: {
message: "Cargando..."
},
fields: {
control: {
searchModeButtonTooltip: "Cambiar a búsqueda",
insertModeButtonTooltip: "Cambiar a inserción",
editButtonTooltip: "Editar",
deleteButtonTooltip: "Suprimir",
searchButtonTooltip: "Buscar",
clearFilterButtonTooltip: "Borrar filtro",
insertButtonTooltip: "Insertar",
updateButtonTooltip: "Actualizar",
cancelEditButtonTooltip: "Cancelar edición"
}
},
validators: {
required: { message: "Campo requerido" },
rangeLength: { message: "La longitud del valor está fuera del intervalo definido" },
minLength: { message: "La longitud del valor es demasiado corta" },
maxLength: { message: "La longitud del valor es demasiado larga" },
pattern: { message: "El valor no se ajusta al patrón definido" },
range: { message: "Valor fuera del rango definido" },
min: { message: "Valor demasiado bajo" },
max: { message: "Valor demasiado alto" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,47 @@
(function(jsGrid) {
jsGrid.locales.fr = {
grid: {
noDataContent: "Pas de données",
deleteConfirm: "Êtes-vous sûr ?",
pagerFormat: "Pages: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} de {pageCount}",
pagePrevText: "<",
pageNextText: ">",
pageFirstText: "<<",
pageLastText: ">>",
loadMessage: "Chargement en cours...",
invalidMessage: "Des données incorrectes sont entrés !"
},
loadIndicator: {
message: "Chargement en cours..."
},
fields: {
control: {
searchModeButtonTooltip: "Recherche",
insertModeButtonTooltip: "Ajouter une entrée",
editButtonTooltip: "Changer",
deleteButtonTooltip: "Effacer",
searchButtonTooltip: "Trouve",
clearFilterButtonTooltip: "Effacer",
insertButtonTooltip: "Ajouter",
updateButtonTooltip: "Sauvegarder",
cancelEditButtonTooltip: "Annuler"
}
},
validators: {
required: { message: "Champ requis" },
rangeLength: { message: "Longueur de la valeur du champ est hors de la plage définie" },
minLength: { message: "La valeur du champ est trop court" },
maxLength: { message: "La valeur du champ est trop long" },
pattern: { message: "La valeur du champ ne correspond pas à la configuration définie" },
range: { message: "La valeur du champ est hors de la plage définie" },
min: { message: "La valeur du champ est trop petit" },
max: { message: "La valeur du champ est trop grande" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,46 @@
(function(jsGrid) {
jsGrid.locales.he = {
grid: {
noDataContent: "לא נמצא",
deleteConfirm: "האם אתה בטוח?",
pagerFormat: "עמודים: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} מתוך {pageCount}",
pagePrevText: "הקודם",
pageNextText: "הבא",
pageFirstText: "ראשון",
pageLastText: "אחרון",
loadMessage: "אנא המתן ...",
invalidMessage: "נתונים לא חוקיים!"
},
loadIndicator: {
message: "טוען..."
},
fields: {
control: {
searchModeButtonTooltip: "ביצוע חיפוש",
insertModeButtonTooltip: "ביצוע עריכת שורה",
editButtonTooltip: "עריכה",
deleteButtonTooltip: "מחיקה",
searchButtonTooltip: "חיפוש",
clearFilterButtonTooltip: "ניקוי מסנן",
insertButtonTooltip: "הכנסה",
updateButtonTooltip: "עדכון",
cancelEditButtonTooltip: "ביטול עריכה"
}
},
validators: {
required: { message: "שדה נדרש" },
rangeLength: { message: "אורכו של הערך הוא מחוץ לטווח המוגדר" },
minLength: { message: "אורכו של הערך קצר מדי" },
maxLength: { message: "אורכו של הערך ארוך מדי" },
pattern: { message: "אורכו של הערך ארוך מדי" },
range: { message: "ערך מחוץ לטווח" },
min: { message: "ערך נמוך מדי" },
max: { message: "גבוה מדי" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,46 @@
(function(jsGrid) {
jsGrid.locales.ja = {
grid: {
noDataContent: "データが見つかりません。",
deleteConfirm: "削除しますよろしですか。",
pagerFormat: "頁: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; 【{pageIndex}{pageCount}】",
pagePrevText: "前",
pageNextText: "次",
pageFirstText: "最初",
pageLastText: "最後",
loadMessage: "しばらくお待ちください…",
invalidMessage: "入力されたデータが不正です。"
},
loadIndicator: {
message: "処理中…"
},
fields: {
control: {
searchModeButtonTooltip: "検索モードへ",
insertModeButtonTooltip: "登録モードへ",
editButtonTooltip: "編集",
deleteButtonTooltip: "削除",
searchButtonTooltip: "フィルター",
clearFilterButtonTooltip: "クリア",
insertButtonTooltip: "登録",
updateButtonTooltip: "更新",
cancelEditButtonTooltip: "編集戻す"
}
},
validators: {
required: { message: "項目が必要です。" },
rangeLength: { message: "項目の桁数が範囲外です。" },
minLength: { message: "項目の桁数が超過しています。" },
maxLength: { message: "項目の桁数が不足しています。" },
pattern: { message: "項目の値がパターンに一致しません。" },
range: { message: "項目の値が範囲外です。" },
min: { message: "項目の値が超過しています。" },
max: { message: "項目の値が不足しています。" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,46 @@
(function(jsGrid) {
jsGrid.locales.ka = {
grid: {
noDataContent: "მონაცემები ცარიელია.",
deleteConfirm: "ნამდვილად გსურთ ჩანაწერის წაშლა?",
pagerFormat: "გვერდები: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} - {pageCount} დან.",
pagePrevText: "<",
pageNextText: ">",
pageFirstText: "<<",
pageLastText: ">>",
loadMessage: "გთხოვთ დაიცადოთ...",
invalidMessage: "შეყვანილია არასწორი მონაცემები!"
},
loadIndicator: {
message: "მიმდინარეობს ჩატვირთვა..."
},
fields: {
control: {
searchModeButtonTooltip: "ძებნა",
insertModeButtonTooltip: "ჩანაწერის დამატება",
editButtonTooltip: "შესწორება",
deleteButtonTooltip: "წაშლა",
searchButtonTooltip: "ძებნა",
clearFilterButtonTooltip: "ფილტრის გასუფთავება",
insertButtonTooltip: "დამატება",
updateButtonTooltip: "შენახვა",
cancelEditButtonTooltip: "გაუქმება"
}
},
validators: {
required: { message: "ველი აუცილებელია შესავსებად." },
rangeLength: { message: "შეყვანილი ჩანაწერის ზომა არ ექვემდებარება დიაპაზონს." },
minLength: { message: "შეყვანილი ჩანაწერის ზომა საკმაოდ პატარა არის." },
maxLength: { message: "შეყვანილი ჩანაწერის ზომა საკმაოდ დიდი არის." },
pattern: { message: "შეყვანილი მნიშვნელობა არ ემთხვევა მითითებულ შაბლონს." },
range: { message: "შეყვანილი ინფორმაცია არ ჯდება დიაპაზონში." },
min: { message: "შეყვანილი ინფორმაციის ზომა საკმაოდ პატარა არის." },
max: { message: "შეყვანილი ინფორმაციის ზომა საკმაოდ დიდი არის." }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,62 @@
(function(jsGrid) {
jsGrid.locales.pl = {
grid: {
noDataContent: "Nie znaleziono",
deleteConfirm: "Czy jesteś pewien?",
pagerFormat: "Strony: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} z {pageCount}",
pagePrevText: "Poprzednia",
pageNextText: "Następna",
pageFirstText: "Pierwsza",
pageLastText: "Ostatnia",
loadMessage: "Proszę czekać...",
invalidMessage: "Wprowadzono nieprawidłowe dane!"
},
loadIndicator: {
message: "Ładowanie..."
},
fields: {
control: {
searchModeButtonTooltip: "Wyszukiwanie",
insertModeButtonTooltip: "Dodawanie",
editButtonTooltip: "Edytuj",
deleteButtonTooltip: "Usuń",
searchButtonTooltip: "Szukaj",
clearFilterButtonTooltip: "Wyczyść filtr",
insertButtonTooltip: "Dodaj",
updateButtonTooltip: "Aktualizuj",
cancelEditButtonTooltip: "Anuluj edytowanie"
}
},
validators: {
required: {
message: "Pole jest wymagane"
},
rangeLength: {
message: "Długość wartości pola znajduje się poza zdefiniowanym zakresem"
},
minLength: {
message: "Wartość pola jest zbyt krótka"
},
maxLength: {
message: "Wartość pola jest zbyt długa"
},
pattern: {
message: "Wartość pola nie zgadza się ze zdefiniowanym wzorem"
},
range: {
message: "Wartość pola znajduje się poza zdefiniowanym zakresem"
},
min: {
message: "Wartość pola jest zbyt mała"
},
max: {
message: "Wartość pola jest zbyt duża"
}
}
};
}(jsGrid, jQuery));

@ -0,0 +1,46 @@
(function(jsGrid) {
jsGrid.locales["pt-br"] = {
grid: {
noDataContent: "Não encontrado",
deleteConfirm: "Você tem certeza que deseja remover este item?",
pagerFormat: "Páginas: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} de {pageCount}",
pagePrevText: "Anterior",
pageNextText: "Seguinte",
pageFirstText: "Primeira",
pageLastText: "Última",
loadMessage: "Por favor, espere...",
invalidMessage: "Dados inválidos!"
},
loadIndicator: {
message: "Carregando..."
},
fields: {
control: {
searchModeButtonTooltip: "Mudar para busca",
insertModeButtonTooltip: "Mudar para inserção",
editButtonTooltip: "Editar",
deleteButtonTooltip: "Remover",
searchButtonTooltip: "Buscar",
clearFilterButtonTooltip: "Remover filtro",
insertButtonTooltip: "Adicionar",
updateButtonTooltip: "Atualizar",
cancelEditButtonTooltip: "Cancelar Edição"
}
},
validators: {
required: { message: "Campo obrigatório" },
rangeLength: { message: "O valor esta fora do intervaldo definido" },
minLength: { message: "O comprimento do valor é muito curto" },
maxLength: { message: "O comprimento valor é muito longo" },
pattern: { message: "O valor informado não é compatível com o padrão" },
range: { message: "O valor informado esta fora do limite definido" },
min: { message: "O valor é muito curto" },
max: { message: "O valor é muito longo" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,46 @@
(function(jsGrid) {
jsGrid.locales.pt = {
grid: {
noDataContent: "Não encontrado",
deleteConfirm: "Você tem certeza que deseja remover este item?",
pagerFormat: "Páginas: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} de {pageCount}",
pagePrevText: "Anterior",
pageNextText: "Seguinte",
pageFirstText: "Primeira",
pageLastText: "Última",
loadMessage: "Por favor, espere...",
invalidMessage: "Dados inválidos!"
},
loadIndicator: {
message: "Carregando..."
},
fields: {
control: {
searchModeButtonTooltip: "Mudar para busca",
insertModeButtonTooltip: "Mudar para inserção",
editButtonTooltip: "Editar",
deleteButtonTooltip: "Remover",
searchButtonTooltip: "Buscar",
clearFilterButtonTooltip: "Remover filtro",
insertButtonTooltip: "Adicionar",
updateButtonTooltip: "Atualizar",
cancelEditButtonTooltip: "Cancelar Edição"
}
},
validators: {
required: { message: "Campo obrigatório" },
rangeLength: { message: "O valor esta fora do intervaldo definido" },
minLength: { message: "O comprimento do valor é muito curto" },
maxLength: { message: "O comprimento valor é muito longo" },
pattern: { message: "O valor informado não é compatível com o padrão" },
range: { message: "O valor informado esta fora do limite definido" },
min: { message: "O valor é muito curto" },
max: { message: "O valor é muito longo" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,47 @@
(function(jsGrid) {
jsGrid.locales.ru = {
grid: {
noDataContent: "Данных не найдено",
deleteConfirm: "Вы действительно хотите удалить запись?",
pagerFormat: "Страницы: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} из {pageCount}",
pagePrevText: "<",
pageNextText: ">",
pageFirstText: "<<",
pageLastText: ">>",
loadMessage: "Пожалуйста, подождите...",
invalidMessage: "Введены неверные данные!"
},
loadIndicator: {
message: "Загрузка..."
},
fields: {
control: {
searchModeButtonTooltip: "Поиск",
insertModeButtonTooltip: "Добавить запись",
editButtonTooltip: "Изменить",
deleteButtonTooltip: "Удалить",
searchButtonTooltip: "Найти",
clearFilterButtonTooltip: "Очистить фильтр",
insertButtonTooltip: "Добавить",
updateButtonTooltip: "Сохранить",
cancelEditButtonTooltip: "Отменить"
}
},
validators: {
required: { message: "Поле обязательно для заполения" },
rangeLength: { message: "Длинна введенного значения вне допустимого диапазона" },
minLength: { message: "Введенное значение слишком короткое" },
maxLength: { message: "Введенное значение слишком длинное" },
pattern: { message: "Введенное значение не соответствует заданному шаблону" },
range: { message: "Введенное значение вне допустимого диапазона" },
min: { message: "Введенное значение слишком маленькое" },
max: { message: "Введенное значение слишком большое" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,47 @@
(function(jsGrid) {
jsGrid.locales.tr = {
grid: {
noDataContent: "Kayıt Bulunamadı",
deleteConfirm: "Emin misiniz ?",
pagerFormat: "Sayfalar: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} / {pageCount}",
pagePrevText: "<",
pageNextText: ">",
pageFirstText: "<<",
pageLastText: ">>",
loadMessage: "Lütfen bekleyiniz...",
invalidMessage: "Geçersiz veri girişi !"
},
loadIndicator: {
message: "Yükleniyor..."
},
fields: {
control: {
searchModeButtonTooltip: "Arama moduna geç",
insertModeButtonTooltip: "Yeni kayıt moduna geç",
editButtonTooltip: "Değiştir",
deleteButtonTooltip: "Sil",
searchButtonTooltip: "Bul",
clearFilterButtonTooltip: "Filtreyi temizle",
insertButtonTooltip: "Ekle",
updateButtonTooltip: "Güncelle",
cancelEditButtonTooltip: "Güncelleme iptali"
}
},
validators: {
required: { message: "Gerekli alandır" },
rangeLength: { message: "Alan değerinin uzunluğu tanımlanan aralık dışındadır" },
minLength: { message: "Alan değeri çok kısadır" },
maxLength: { message: "Alan değeri çok uzundur" },
pattern: { message: "Alan değeri tanımlanan şablon ile eşleşmiyor" },
range: { message: "Alan değeri tanımlı aralığın dışındadır" },
min: { message: "Alan değeri çok küçüktür" },
max: { message: "Alan değeri çok büyüktür" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,46 @@
(function(jsGrid) {
jsGrid.locales["zh-cn"] = {
grid: {
noDataContent: "暂无数据",
deleteConfirm: "确认删除?",
pagerFormat: "页码: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} / {pageCount}",
pagePrevText: "上一页",
pageNextText: "下一页",
pageFirstText: "第一页",
pageLastText: "最后页",
loadMessage: "请稍后...",
invalidMessage: "数据有误!"
},
loadIndicator: {
message: "载入中..."
},
fields: {
control: {
searchModeButtonTooltip: "切换为搜索",
insertModeButtonTooltip: "切换为新增",
editButtonTooltip: "编辑",
deleteButtonTooltip: "删除",
searchButtonTooltip: "搜索",
clearFilterButtonTooltip: "清空过滤",
insertButtonTooltip: "插入",
updateButtonTooltip: "更新",
cancelEditButtonTooltip: "取消编辑"
}
},
validators: {
required: { message: "字段必填" },
rangeLength: { message: "字段值长度超过定义范围" },
minLength: { message: "字段长度过短" },
maxLength: { message: "字段长度过长" },
pattern: { message: "字段值不符合定义规则" },
range: { message: "字段值超过定义范围" },
min: { message: "字段值太小" },
max: { message: "字段值太大" }
}
};
}(jsGrid, jQuery));

@ -0,0 +1,46 @@
(function(jsGrid) {
jsGrid.locales["zh-tw"] = {
grid: {
noDataContent: "暫無資料",
deleteConfirm: "確認刪除?",
pagerFormat: "頁碼: {first} {prev} {pages} {next} {last} &nbsp;&nbsp; {pageIndex} / {pageCount}",
pagePrevText: "上一頁",
pageNextText: "下一頁",
pageFirstText: "第一頁",
pageLastText: "最後一頁",
loadMessage: "請稍候...",
invalidMessage: "輸入資料不正確"
},
loadIndicator: {
message: "載入中..."
},
fields: {
control: {
searchModeButtonTooltip: "切換為搜尋",
insertModeButtonTooltip: "切換為新增",
editButtonTooltip: "編輯",
deleteButtonTooltip: "刪除",
searchButtonTooltip: "搜尋",
clearFilterButtonTooltip: "清除搜尋條件",
insertButtonTooltip: "新增",
updateButtonTooltip: "修改",
cancelEditButtonTooltip: "取消編輯"
}
},
validators: {
required: { message: "欄位必填" },
rangeLength: { message: "欄位字串長度超出範圍" },
minLength: { message: "欄位字串長度太短" },
maxLength: { message: "欄位字串長度太長" },
pattern: { message: "欄位字串不符合規則" },
range: { message: "欄位數值超出範圍" },
min: { message: "欄位數值太小" },
max: { message: "欄位數值太大" }
}
};
}(jsGrid, jQuery));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,126 @@
/*
* jsGrid v1.5.2 (http://js-grid.com)
* (c) 2016 Artem Tabalin
* Licensed under MIT (https://github.com/tabalinas/jsgrid/blob/master/LICENSE)
*/
.jsgrid {
position: relative;
overflow: hidden;
font-size: 1em;
}
.jsgrid, .jsgrid *, .jsgrid *:before, .jsgrid *:after {
box-sizing: border-box;
}
.jsgrid input,
.jsgrid textarea,
.jsgrid select {
font-size: 1em;
}
.jsgrid-grid-header {
overflow-x: hidden;
overflow-y: scroll;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
.jsgrid-grid-body {
overflow-x: auto;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.jsgrid-table {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
border-spacing: 0;
}
.jsgrid-cell {
padding: 0.5em 0.5em;
}
.jsgrid-сell,
.jsgrid-header-cell {
box-sizing: border-box;
}
.jsgrid-align-left {
text-align: left;
}
.jsgrid-align-center,
.jsgrid-align-center input,
.jsgrid-align-center textarea,
.jsgrid-align-center select {
text-align: center;
}
.jsgrid-align-right,
.jsgrid-align-right input,
.jsgrid-align-right textarea,
.jsgrid-align-right select {
text-align: right;
}
.jsgrid-header-cell {
padding: .5em .5em;
}
.jsgrid-filter-row input,
.jsgrid-filter-row textarea,
.jsgrid-filter-row select,
.jsgrid-edit-row input,
.jsgrid-edit-row textarea,
.jsgrid-edit-row select,
.jsgrid-insert-row input,
.jsgrid-insert-row textarea,
.jsgrid-insert-row select {
width: 100%;
padding: .3em .5em;
}
.jsgrid-filter-row input[type='checkbox'],
.jsgrid-edit-row input[type='checkbox'],
.jsgrid-insert-row input[type='checkbox'] {
width: auto;
}
.jsgrid-selected-row .jsgrid-cell {
cursor: pointer;
}
.jsgrid-nodata-row .jsgrid-cell {
padding: .5em 0;
text-align: center;
}
.jsgrid-header-sort {
cursor: pointer;
}
.jsgrid-pager {
padding: .5em 0;
}
.jsgrid-pager-nav-button {
padding: .2em .6em;
}
.jsgrid-pager-nav-inactive-button {
display: none;
pointer-events: none;
}
.jsgrid-pager-page {
padding: .2em .6em;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,7 @@
/*
* jsGrid v1.5.2 (http://js-grid.com)
* (c) 2016 Artem Tabalin
* Licensed under MIT (https://github.com/tabalinas/jsgrid/blob/master/LICENSE)
*/
.jsgrid{position:relative;overflow:hidden;font-size:1em}.jsgrid,.jsgrid *,.jsgrid :after,.jsgrid :before{box-sizing:border-box}.jsgrid input,.jsgrid select,.jsgrid textarea{font-size:1em}.jsgrid-grid-header{overflow-x:hidden;overflow-y:scroll;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.jsgrid-grid-body{overflow-x:auto;overflow-y:scroll;-webkit-overflow-scrolling:touch}.jsgrid-table{width:100%;table-layout:fixed;border-collapse:collapse;border-spacing:0}.jsgrid-cell{padding:.5em}.jsgrid-header-cell,.jsgrid-сell{box-sizing:border-box}.jsgrid-align-left{text-align:left}.jsgrid-align-center,.jsgrid-align-center input,.jsgrid-align-center select,.jsgrid-align-center textarea{text-align:center}.jsgrid-align-right,.jsgrid-align-right input,.jsgrid-align-right select,.jsgrid-align-right textarea{text-align:right}.jsgrid-header-cell{padding:.5em}.jsgrid-edit-row input,.jsgrid-edit-row select,.jsgrid-edit-row textarea,.jsgrid-filter-row input,.jsgrid-filter-row select,.jsgrid-filter-row textarea,.jsgrid-insert-row input,.jsgrid-insert-row select,.jsgrid-insert-row textarea{width:100%;padding:.3em .5em}.jsgrid-edit-row input[type=checkbox],.jsgrid-filter-row input[type=checkbox],.jsgrid-insert-row input[type=checkbox]{width:auto}.jsgrid-selected-row .jsgrid-cell{cursor:pointer}.jsgrid-nodata-row .jsgrid-cell{padding:.5em 0;text-align:center}.jsgrid-header-sort{cursor:pointer}.jsgrid-pager{padding:.5em 0}.jsgrid-pager-nav-button{padding:.2em .6em}.jsgrid-pager-nav-inactive-button{display:none;pointer-events:none}.jsgrid-pager-page{padding:.2em .6em}

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save