Allow deploying to pythonanywhere from the web2py admin that you're running locally.
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import base64
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import gzip
|
||||||
|
import tarfile
|
||||||
|
try:
|
||||||
|
from cStringIO import StringIO
|
||||||
|
except ImportError:
|
||||||
|
from StringIO import StringIO
|
||||||
|
from xmlrpclib import ProtocolError
|
||||||
|
from gluon.contrib.simplejsonrpc import ServerProxy
|
||||||
|
|
||||||
|
|
||||||
|
def deploy():
|
||||||
|
response.title = T('Deploy to pythonanywhere')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def crossdomainproxy():
|
||||||
|
if not request.vars:
|
||||||
|
raise HTTP(400)
|
||||||
|
import urllib, urllib2
|
||||||
|
url = 'https://www.pythonanywhere.com/api/web2py/create_account'
|
||||||
|
data = urllib.urlencode(request.vars)
|
||||||
|
req = urllib2.Request(url, data)
|
||||||
|
try:
|
||||||
|
reply = urllib2.urlopen(req)
|
||||||
|
except urllib2.HTTPError as error:
|
||||||
|
if error.code == 400:
|
||||||
|
reply = error
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
response.headers['Content-Type'] = 'application/json'
|
||||||
|
return reply.read()
|
||||||
|
|
||||||
|
|
||||||
|
def list_apps():
|
||||||
|
""" Get a list of apps both remote and local """
|
||||||
|
if not request.vars.username or not request.vars.password:
|
||||||
|
raise HTTP(400)
|
||||||
|
client = ServerProxy('https://%(username)s:%(password)s@%(username)s.pythonanywhere.com/admin/webservices/call/jsonrpc' % request.vars)
|
||||||
|
regex = re.compile('^\w+$')
|
||||||
|
local = [f for f in os.listdir(apath(r=request)) if regex.match(f)]
|
||||||
|
try:
|
||||||
|
pythonanywhere = client.list_apps()
|
||||||
|
except ProtocolError as error:
|
||||||
|
raise HTTP(error.errcode)
|
||||||
|
return response.json({'local': local, 'pythonanywhere': pythonanywhere})
|
||||||
|
|
||||||
|
|
||||||
|
def bulk_install():
|
||||||
|
""" Install a list of apps """
|
||||||
|
|
||||||
|
def b64pack(app):
|
||||||
|
"""
|
||||||
|
Given an app's name, return the base64 representation of its packed version.
|
||||||
|
"""
|
||||||
|
folder = apath(app, r=request)
|
||||||
|
tmpfile = StringIO()
|
||||||
|
tar = tarfile.TarFile(fileobj=tmpfile, mode='w')
|
||||||
|
try:
|
||||||
|
filenames = listdir(folder, '^[\w\.\-]+$', add_dirs=True,
|
||||||
|
exclude_content_from=['cache', 'sessions', 'errors'])
|
||||||
|
for fname in filenames:
|
||||||
|
tar.add(os.path.join(folder, fname), fname, False)
|
||||||
|
finally:
|
||||||
|
tar.close()
|
||||||
|
tmpfile.seek(0)
|
||||||
|
gzfile = StringIO()
|
||||||
|
w2pfp = gzip.GzipFile(fileobj=gzfile, mode='wb')
|
||||||
|
w2pfp.write(tmpfile.read())
|
||||||
|
w2pfp.close()
|
||||||
|
gzfile.seek(0)
|
||||||
|
return base64.b64encode(gzfile.read())
|
||||||
|
|
||||||
|
request.vars.apps = request.vars['apps[]']
|
||||||
|
if not request.vars.apps or not request.vars.username or not request.vars.password:
|
||||||
|
raise HTTP(400)
|
||||||
|
if not isinstance(request.vars.apps, list):
|
||||||
|
request.vars.apps = [request.vars.apps] # Only one app selected
|
||||||
|
|
||||||
|
client = ServerProxy('https://%(username)s:%(password)s@%(username)s.pythonanywhere.com/admin/webservices/call/jsonrpc' % request.vars)
|
||||||
|
|
||||||
|
for app in request.vars.apps:
|
||||||
|
try:
|
||||||
|
client.install(app, app+'.w2p', b64pack(app))
|
||||||
|
except ProtocolError as error:
|
||||||
|
raise HTTP(error.errcode)
|
||||||
|
|
||||||
|
return response.json({'status': 'ok'})
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
'A new version of web2py is available: %s': 'Está disponível uma nova versão do web2py: %s',
|
'A new version of web2py is available: %s': 'Está disponível uma nova versão do web2py: %s',
|
||||||
'About': 'sobre',
|
'About': 'sobre',
|
||||||
'About application': 'Sobre a aplicação',
|
'About application': 'Sobre a aplicação',
|
||||||
|
'Accept Terms': 'Accept Terms',
|
||||||
'additional code for your application': 'código adicional para sua aplicação',
|
'additional code for your application': 'código adicional para sua aplicação',
|
||||||
'Additional code for your application': 'Código adicional para a sua aplicação',
|
'Additional code for your application': 'Código adicional para a sua aplicação',
|
||||||
'admin disabled because no admin password': ' admin desabilitado por falta de senha definida',
|
'admin disabled because no admin password': ' admin desabilitado por falta de senha definida',
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
'Autocomplete Python Code': 'Autocompletar Código Python',
|
'Autocomplete Python Code': 'Autocompletar Código Python',
|
||||||
'Available databases and tables': 'Bancos de dados e tabelas disponíveis',
|
'Available databases and tables': 'Bancos de dados e tabelas disponíveis',
|
||||||
'back': 'voltar',
|
'back': 'voltar',
|
||||||
|
'Begin': 'Begin',
|
||||||
'browse': 'buscar',
|
'browse': 'buscar',
|
||||||
'cache': 'cache',
|
'cache': 'cache',
|
||||||
'cache, errors and sessions cleaned': 'cache, erros e sessões eliminadas',
|
'cache, errors and sessions cleaned': 'cache, erros e sessões eliminadas',
|
||||||
@@ -112,11 +114,15 @@
|
|||||||
'Deploy': 'publicar',
|
'Deploy': 'publicar',
|
||||||
'Deploy on Google App Engine': 'Publicar no Google App Engine',
|
'Deploy on Google App Engine': 'Publicar no Google App Engine',
|
||||||
'Deploy to OpenShift': 'Deploy to OpenShift',
|
'Deploy to OpenShift': 'Deploy to OpenShift',
|
||||||
|
'Deploy to pythonanywhere': 'Deploy to pythonanywhere',
|
||||||
|
'Deploy to PythonAnywhere': 'Deploy to PythonAnywhere',
|
||||||
|
'Deployment Interface': 'Deployment Interface',
|
||||||
'Description': 'Descrição',
|
'Description': 'Descrição',
|
||||||
'design': 'modificar',
|
'design': 'modificar',
|
||||||
'DESIGN': 'Projeto',
|
'DESIGN': 'Projeto',
|
||||||
'Design for': 'Projeto de',
|
'Design for': 'Projeto de',
|
||||||
'Detailed traceback description': 'Detailed traceback description',
|
'Detailed traceback description': 'Detailed traceback description',
|
||||||
|
'details': 'details',
|
||||||
'direction: ltr': 'direção: ltr',
|
'direction: ltr': 'direção: ltr',
|
||||||
'Disable': 'Disable',
|
'Disable': 'Disable',
|
||||||
'docs': 'docs',
|
'docs': 'docs',
|
||||||
@@ -137,6 +143,7 @@
|
|||||||
'Editing file': 'Editando arquivo',
|
'Editing file': 'Editando arquivo',
|
||||||
'Editing file "%s"': 'Editando arquivo "%s"',
|
'Editing file "%s"': 'Editando arquivo "%s"',
|
||||||
'Editing Language file': 'Editando arquivo de linguagem',
|
'Editing Language file': 'Editando arquivo de linguagem',
|
||||||
|
'Email Address': 'Email Address',
|
||||||
'Enterprise Web Framework': 'Framework web empresarial',
|
'Enterprise Web Framework': 'Framework web empresarial',
|
||||||
'Error': 'Erro',
|
'Error': 'Erro',
|
||||||
'Error logs for "%(app)s"': 'Logs de erro para "%(app)s"',
|
'Error logs for "%(app)s"': 'Logs de erro para "%(app)s"',
|
||||||
@@ -148,6 +155,7 @@
|
|||||||
'Expand Abbreviation (html files only)': 'Expandir Abreviação (só para ficheiros html)',
|
'Expand Abbreviation (html files only)': 'Expandir Abreviação (só para ficheiros html)',
|
||||||
'export as csv file': 'exportar como arquivo CSV',
|
'export as csv file': 'exportar como arquivo CSV',
|
||||||
'exposes': 'expõe',
|
'exposes': 'expõe',
|
||||||
|
'exposes:': 'exposes:',
|
||||||
'extends': 'estende',
|
'extends': 'estende',
|
||||||
'failed to reload module': 'Falha ao recarregar o módulo',
|
'failed to reload module': 'Falha ao recarregar o módulo',
|
||||||
'failed to reload module because:': 'falha ao recarregar o módulo por:',
|
'failed to reload module because:': 'falha ao recarregar o módulo por:',
|
||||||
@@ -165,6 +173,7 @@
|
|||||||
'Find Next': 'Localizar Seguinte',
|
'Find Next': 'Localizar Seguinte',
|
||||||
'Find Previous': 'Localizar Anterior',
|
'Find Previous': 'Localizar Anterior',
|
||||||
'First name': 'Nome',
|
'First name': 'Nome',
|
||||||
|
'Form has errors': 'Form has errors',
|
||||||
'Frames': 'Frames',
|
'Frames': 'Frames',
|
||||||
'Functions with no doctests will result in [passed] tests.': 'Funções sem doctests resultarão em testes [aceitos].',
|
'Functions with no doctests will result in [passed] tests.': 'Funções sem doctests resultarão em testes [aceitos].',
|
||||||
'graph model': 'graph model',
|
'graph model': 'graph model',
|
||||||
@@ -198,11 +207,16 @@
|
|||||||
'Last name': 'Sobrenome',
|
'Last name': 'Sobrenome',
|
||||||
'Last saved on:': 'Salvo em:',
|
'Last saved on:': 'Salvo em:',
|
||||||
'License for': 'Licença para',
|
'License for': 'Licença para',
|
||||||
|
'lists by ticket': 'lists by ticket',
|
||||||
|
'Loading...': 'Loading...',
|
||||||
'loading...': 'carregando...',
|
'loading...': 'carregando...',
|
||||||
|
'Local Apps': 'Local Apps',
|
||||||
'locals': 'locals',
|
'locals': 'locals',
|
||||||
'Login': 'Entrar',
|
'Login': 'Entrar',
|
||||||
'login': 'inicio de sessão',
|
'login': 'inicio de sessão',
|
||||||
|
'Login successful': 'Login successful',
|
||||||
'Login to the Administrative Interface': 'Entrar na interface adminitrativa',
|
'Login to the Administrative Interface': 'Entrar na interface adminitrativa',
|
||||||
|
'Login/Register': 'Login/Register',
|
||||||
'Logout': 'finalizar sessão',
|
'Logout': 'finalizar sessão',
|
||||||
'Lost Password': 'Senha perdida',
|
'Lost Password': 'Senha perdida',
|
||||||
'Manage': 'Manage',
|
'Manage': 'Manage',
|
||||||
@@ -214,6 +228,7 @@
|
|||||||
'modules': 'módulos',
|
'modules': 'módulos',
|
||||||
'Name': 'Nome',
|
'Name': 'Nome',
|
||||||
'new application "%s" created': 'nova aplicação "%s" criada',
|
'new application "%s" created': 'nova aplicação "%s" criada',
|
||||||
|
'New Application Wizard': 'New Application Wizard',
|
||||||
'New application wizard': 'Assistente para novas aplicações ',
|
'New application wizard': 'Assistente para novas aplicações ',
|
||||||
'new plugin installed': 'novo plugin instalado',
|
'new plugin installed': 'novo plugin instalado',
|
||||||
'New Record': 'Novo registro',
|
'New Record': 'Novo registro',
|
||||||
@@ -224,6 +239,7 @@
|
|||||||
'No databases in this application': 'Não existem bancos de dados nesta aplicação',
|
'No databases in this application': 'Não existem bancos de dados nesta aplicação',
|
||||||
'no match': 'não encontrado',
|
'no match': 'não encontrado',
|
||||||
'no package selected': 'nenhum pacote selecionado',
|
'no package selected': 'nenhum pacote selecionado',
|
||||||
|
'No ticket_storage.txt found under /private folder': 'No ticket_storage.txt found under /private folder',
|
||||||
'online designer': 'online designer',
|
'online designer': 'online designer',
|
||||||
'or alternatively': 'or alternatively',
|
'or alternatively': 'or alternatively',
|
||||||
'Or Get from URL:': 'Ou Obtenha do URL:',
|
'Or Get from URL:': 'Ou Obtenha do URL:',
|
||||||
@@ -241,6 +257,7 @@
|
|||||||
'Password': 'Senha',
|
'Password': 'Senha',
|
||||||
'password changed': 'senha alterada',
|
'password changed': 'senha alterada',
|
||||||
'Peeking at file': 'Visualizando arquivo',
|
'Peeking at file': 'Visualizando arquivo',
|
||||||
|
'Please wait, giving pythonanywhere a moment...': 'Please wait, giving pythonanywhere a moment...',
|
||||||
'plugin "%(plugin)s" deleted': 'plugin "%(plugin)s" eliminado',
|
'plugin "%(plugin)s" deleted': 'plugin "%(plugin)s" eliminado',
|
||||||
'Plugin "%s" in application': 'Plugin "%s" na aplicação',
|
'Plugin "%s" in application': 'Plugin "%s" na aplicação',
|
||||||
'plugins': 'plugins',
|
'plugins': 'plugins',
|
||||||
@@ -250,6 +267,8 @@
|
|||||||
'previous 100 rows': '100 registros anteriores',
|
'previous 100 rows': '100 registros anteriores',
|
||||||
'Private files': 'Private files',
|
'Private files': 'Private files',
|
||||||
'private files': 'private files',
|
'private files': 'private files',
|
||||||
|
'PythonAnywhere Apps': 'PythonAnywhere Apps',
|
||||||
|
'PythonAnywhere Password': 'PythonAnywhere Password',
|
||||||
'Query:': 'Consulta:',
|
'Query:': 'Consulta:',
|
||||||
'Rapid Search': 'Rapid Search',
|
'Rapid Search': 'Rapid Search',
|
||||||
'record': 'registro',
|
'record': 'registro',
|
||||||
@@ -263,6 +282,7 @@
|
|||||||
'Replace': 'Substituir',
|
'Replace': 'Substituir',
|
||||||
'Replace All': 'Substituir Tudo',
|
'Replace All': 'Substituir Tudo',
|
||||||
'request': 'request',
|
'request': 'request',
|
||||||
|
'requires python-git, but not installed': 'requires python-git, but not installed',
|
||||||
'Resolve Conflict file': 'Arquivo de resolução de conflito',
|
'Resolve Conflict file': 'Arquivo de resolução de conflito',
|
||||||
'response': 'response',
|
'response': 'response',
|
||||||
'restore': 'restaurar',
|
'restore': 'restaurar',
|
||||||
@@ -285,6 +305,9 @@
|
|||||||
'shell': 'Terminal',
|
'shell': 'Terminal',
|
||||||
'Site': 'site',
|
'Site': 'site',
|
||||||
'some files could not be removed': 'alguns arquicos não puderam ser removidos',
|
'some files could not be removed': 'alguns arquicos não puderam ser removidos',
|
||||||
|
'Something went wrong please wait a few minutes before retrying': 'Something went wrong please wait a few minutes before retrying',
|
||||||
|
'source : filesystem': 'source : filesystem',
|
||||||
|
'Start a new app': 'Start a new app',
|
||||||
'Start searching': 'Start searching',
|
'Start searching': 'Start searching',
|
||||||
'Start wizard': 'iniciar assistente',
|
'Start wizard': 'iniciar assistente',
|
||||||
'state': 'estado',
|
'state': 'estado',
|
||||||
@@ -294,6 +317,7 @@
|
|||||||
'Submit': 'Submit',
|
'Submit': 'Submit',
|
||||||
'submit': 'enviar',
|
'submit': 'enviar',
|
||||||
'Sure you want to delete this object?': 'Tem certeza que deseja apaagr este objeto?',
|
'Sure you want to delete this object?': 'Tem certeza que deseja apaagr este objeto?',
|
||||||
|
'switch to : db': 'switch to : db',
|
||||||
'table': 'tabela',
|
'table': 'tabela',
|
||||||
'Table name': 'Nome da tabela',
|
'Table name': 'Nome da tabela',
|
||||||
'test': 'testar',
|
'test': 'testar',
|
||||||
@@ -348,6 +372,7 @@
|
|||||||
'update': 'atualizar',
|
'update': 'atualizar',
|
||||||
'update all languages': 'atualizar todas as linguagens',
|
'update all languages': 'atualizar todas as linguagens',
|
||||||
'Update:': 'Atualizar:',
|
'Update:': 'Atualizar:',
|
||||||
|
'upgrade now to %s': 'upgrade now to %s',
|
||||||
'upgrade web2py now': 'atualize o web2py agora',
|
'upgrade web2py now': 'atualize o web2py agora',
|
||||||
'upload': 'upload',
|
'upload': 'upload',
|
||||||
'Upload': 'Upload',
|
'Upload': 'Upload',
|
||||||
@@ -361,6 +386,7 @@
|
|||||||
'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) para AND, (...)|(...) para OR, y ~(...) para NOT, para criar consultas mais complexas.',
|
'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Use (...)&(...) para AND, (...)|(...) para OR, y ~(...) para NOT, para criar consultas mais complexas.',
|
||||||
'Use an url:': 'Use uma url:',
|
'Use an url:': 'Use uma url:',
|
||||||
'User ID': 'ID do Usuario',
|
'User ID': 'ID do Usuario',
|
||||||
|
'Username': 'Username',
|
||||||
'variables': 'variáveis',
|
'variables': 'variáveis',
|
||||||
'Version': 'Versão',
|
'Version': 'Versão',
|
||||||
'versioning': 'versionamento',
|
'versioning': 'versionamento',
|
||||||
@@ -369,6 +395,7 @@
|
|||||||
'Views': 'Visões',
|
'Views': 'Visões',
|
||||||
'views': 'visões',
|
'views': 'visões',
|
||||||
'Web Framework': 'Web Framework',
|
'Web Framework': 'Web Framework',
|
||||||
|
'web2py Admin Password': 'web2py Admin Password',
|
||||||
'web2py is up to date': 'web2py está atualizado',
|
'web2py is up to date': 'web2py está atualizado',
|
||||||
'web2py Recent Tweets': 'Tweets Recentes de @web2py',
|
'web2py Recent Tweets': 'Tweets Recentes de @web2py',
|
||||||
'web2py upgraded; please restart it': 'web2py atualizado; favor reiniciar',
|
'web2py upgraded; please restart it': 'web2py atualizado; favor reiniciar',
|
||||||
|
|||||||
@@ -138,6 +138,7 @@
|
|||||||
<p class="row-buttons">
|
<p class="row-buttons">
|
||||||
{{=button(URL('gae','deploy'), T('Deploy on Google App Engine'))}}
|
{{=button(URL('gae','deploy'), T('Deploy on Google App Engine'))}}
|
||||||
{{=button(URL('openshift','deploy'),T('Deploy to OpenShift'))}}
|
{{=button(URL('openshift','deploy'),T('Deploy to OpenShift'))}}
|
||||||
|
{{=button(URL('pythonanywhere','deploy'), T('Deploy to PythonAnywhere'))}}
|
||||||
</p>
|
</p>
|
||||||
</div> <!-- /DEPLOY ON GAE -->
|
</div> <!-- /DEPLOY ON GAE -->
|
||||||
<!-- APP WIZARD -->
|
<!-- APP WIZARD -->
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
{{extend 'layout.html'}}
|
||||||
|
<h2><span style="color:#139FD7">python</span>anywhere {{=T('Deployment Interface')}}</h2>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="register_form">
|
||||||
|
<h3>{{=T('Login/Register')}}</h3>
|
||||||
|
<form class="form-horizontal" id="palogin">
|
||||||
|
|
||||||
|
<div class="control-group" id="username__row">
|
||||||
|
<label class="control-label" for="username">{{=T('Username')}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" name="username" id="username">
|
||||||
|
<span class="help-block"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group" id="email_address__row">
|
||||||
|
<label class="control-label" for="email_address">{{=T('Email Address')}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" name="email_address" id="email_address">
|
||||||
|
<span class="help-block"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group" id="pythonanywhere_password__row">
|
||||||
|
<label class="control-label" for="pythonanywhere_password">{{=T('PythonAnywhere Password')}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="password" name="pythonanywhere_password" id="pythonanywhere_password">
|
||||||
|
<span class="help-block"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group" id="web2py_admin_password__row">
|
||||||
|
<label class="control-label" for="web2py_admin_password">{{=T('web2py Admin Password')}}</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="password" name="web2py_admin_password" id="web2py_admin_password">
|
||||||
|
<span class="help-block"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group" id="accepts_terms__row">
|
||||||
|
<div class="controls">
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox" name="accepts_terms" id="accepts_terms"> {{=T('Accept Terms')}}
|
||||||
|
</label>
|
||||||
|
<span class="help-block"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="controls">
|
||||||
|
<button type="submit" class="btn btn-primary" id="submit_palogin">{{=T('Submit')}}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row-fluid" id="app_manager" style="display:none;">
|
||||||
|
<div class="span6">
|
||||||
|
<h3>{{=T('Local Apps')}}</h3>
|
||||||
|
<form id="apppicker">
|
||||||
|
<select name="apps" class="form-control" id="local" multiple>
|
||||||
|
<option>{{=T('Loading...')}}</option>
|
||||||
|
</select>
|
||||||
|
<input type="submit" value="Deploy" id="deploy_button" class="btn btn-primary">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="span6">
|
||||||
|
<h3>{{=T('PythonAnywhere Apps')}}</h3>
|
||||||
|
<ul id="pythonanywhere">
|
||||||
|
<li>{{=T('Loading...')}}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
$('#palogin').off('submit');
|
||||||
|
$('#palogin').submit(function(event) {
|
||||||
|
var data = $('#palogin').serialize();
|
||||||
|
$.web2py.disableElement($('#submit_palogin'));
|
||||||
|
$.web2py.disableFormElements($('#palogin'));
|
||||||
|
$.ajax({
|
||||||
|
url: '{{=URL("pythonanywhere", "crossdomainproxy")}}',
|
||||||
|
type: 'POST',
|
||||||
|
data: data,
|
||||||
|
dataType: 'json',
|
||||||
|
}).done(function(data, textStatus, jqXHR) {
|
||||||
|
console.log(data);
|
||||||
|
$('#palogin .error').removeClass('error');
|
||||||
|
$('#palogin .help-block').text('');
|
||||||
|
if(data.status == 'error') {
|
||||||
|
for(var error in data.errors) {
|
||||||
|
$('#' + error + '__row').addClass('error');
|
||||||
|
$('#' + error + '__row .help-block').text(data.errors[error][0]);
|
||||||
|
}
|
||||||
|
$.web2py.enableElement($('#submit_palogin'));
|
||||||
|
$.web2py.enableFormElements($('#palogin'));
|
||||||
|
$.web2py.flash("{{=T('Form has errors')}}");
|
||||||
|
} else {
|
||||||
|
$.web2py.flash("{{=T('Login successful')}}");
|
||||||
|
$('#register_form').hide();
|
||||||
|
$('#app_manager').show();
|
||||||
|
refresh_apps();
|
||||||
|
}
|
||||||
|
}).fail(function(){
|
||||||
|
$.web2py.flash("{{=T('Something went wrong please wait a few minutes before retrying')}}");
|
||||||
|
$.web2py.enableElement($('#submit_palogin'));
|
||||||
|
$.web2py.enableFormElements($('#palogin'));
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#apppicker').off('submit');
|
||||||
|
$('#apppicker').submit(function(event) {
|
||||||
|
var data = $('#apppicker').serialize();
|
||||||
|
$.web2py.disableElement($('#deploy_button'));
|
||||||
|
$.ajax({
|
||||||
|
url: '{{=URL("pythonanywhere", "bulk_install")}}',
|
||||||
|
type: 'POST',
|
||||||
|
data: {username: $('#username').val(), password: $('#web2py_admin_password').val(), apps: $('#local').val()},
|
||||||
|
dataType: 'json',
|
||||||
|
}).done(function(data, textStatus, jqXHR) {
|
||||||
|
console.log(data);
|
||||||
|
refresh_apps();
|
||||||
|
$.web2py.enableElement($('#deploy_button'));
|
||||||
|
}).fail(function(){
|
||||||
|
$.web2py.flash("{{=T('Something went wrong please wait a few minutes before retrying')}}");
|
||||||
|
$.web2py.enableElement($('#deploy_button'));
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function refresh_apps() {
|
||||||
|
// Refresh List of Apps
|
||||||
|
$('#deploy_button').prop('disabled', true);
|
||||||
|
$.ajax({
|
||||||
|
url: '{{=URL("pythonanywhere", "list_apps")}}',
|
||||||
|
type: 'GET',
|
||||||
|
data: {username: $('#username').val(), password: $('#web2py_admin_password').val()},
|
||||||
|
dataType: 'json',
|
||||||
|
}).done(function(data, textStatus, jqXHR) {
|
||||||
|
var i = 0;
|
||||||
|
$('#local').html('')
|
||||||
|
for(i = 0; i < data.local.length; i++) {
|
||||||
|
$('#local').append($('<option>', {
|
||||||
|
value: data.local[i],
|
||||||
|
text: data.local[i]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
$('#local').multiSelect('refresh');
|
||||||
|
$('#pythonanywhere').html('')
|
||||||
|
for(i = 0; i < data.pythonanywhere.length; i++) {
|
||||||
|
$('#pythonanywhere').append($('<li>', {
|
||||||
|
text: data.pythonanywhere[i]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
$('#deploy_button').prop('disabled', false);
|
||||||
|
$.web2py.hide_flash();
|
||||||
|
}).fail(function(){
|
||||||
|
// Mostly this happens if it's a new account, just waiting a bit should be enough.
|
||||||
|
$.get('http://' + $('#username').val() + '.pythonanywhere.com'); // Kickstart the instance
|
||||||
|
$.web2py.flash("{{=T('Please wait, giving pythonanywhere a moment...')}}");
|
||||||
|
setTimeout(refresh_apps, 30000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
Reference in New Issue
Block a user