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)
|
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} {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} {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} {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} {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} {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} {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} {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} {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} {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-cn"] = {
|
||||||
|
grid: {
|
||||||
|
noDataContent: "暂无数据",
|
||||||
|
deleteConfirm: "确认删除?",
|
||||||
|
pagerFormat: "页码: {first} {prev} {pages} {next} {last} {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} {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
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue