diff --git a/bootstrap/webapp/templates/layout.html b/bootstrap/webapp/templates/layout.html index 3517de0..b183f2c 100644 --- a/bootstrap/webapp/templates/layout.html +++ b/bootstrap/webapp/templates/layout.html @@ -205,9 +205,7 @@ -{% block script %} -{% endblock %} +{% block script %}{% endblock %} diff --git a/oshipka.sh b/oshipka.sh index 955669e..7d5877e 100755 --- a/oshipka.sh +++ b/oshipka.sh @@ -21,6 +21,8 @@ Usage $0 [ bootstrap | model | db_migrate | db_upgrade | db_populate | db_recrea db_recreate Delete the database, recreate to latest migration and populate db_purge_recreate Same as db_recreate but also purge the migrations + translate Translations subcommand + worker Start worker web Start webapp @@ -33,6 +35,36 @@ Usage $0 [ bootstrap | model | db_migrate | db_upgrade | db_populate | db_recrea cert [DOMAIN] Install certificate " +#!/usr/bin/env bash + +HELP_TRANSLATION=" +USAGE ./manage.sh translate [extract|gen {lang}|compile|update] + + extract Extract strings in files as defined in translations/babel.cfg + gen {lang} Init translations for {lang} + compile Compile all translations + update Use after a new extract - it may mark strings as fuzzy. +" + +command_translate() { + TRANSLATE_COMMAND=$1 + shift + case "$TRANSLATE_COMMAND" in + extract) pybabel extract -F translations/babel.cfg -o translations/messages.pot . + ;; + gen) pybabel init -i translations/messages.pot -d translations -l "$@" + ;; + compile) pybabel compile -d translations + ;; + update) pybabel update -i translations/messages.pot -d translations + ;; + *) >&2 echo -e "${HELP_TRANSLATION}" + ;; + esac + return $? +} + + worker () { source venv/bin/activate python worker.py @@ -287,6 +319,8 @@ command_main() { ;; db_purge_recreate) db_purge_recreate "$@" ;; + translate) command_translate "$@" + ;; init) init "$@" ;; download_sensitive) download_sensitive "$@" diff --git a/oshipka/webapp/views.py b/oshipka/webapp/views.py index c9ab271..56ddff5 100644 --- a/oshipka/webapp/views.py +++ b/oshipka/webapp/views.py @@ -144,7 +144,7 @@ class ViewContext(object): jsonify_func=None, render_func=None, template_func=None, template_ctx_func=None, should_redirect_no_instances_func=None, should_redirect_at_end_func=None, - is_json=False, **kwargs): + is_json=False, model_view=None, **kwargs): self.args_get_func = args_get_func or default_get_args_func self.args_process_func = args_process_func or default_none_func self.filter_func = filter_func or default_none_func @@ -161,6 +161,7 @@ class ViewContext(object): self.template_ctx_func = template_ctx_func or default_none_func self.should_redirect_at_end_func = should_redirect_at_end_func or default_none_func self.is_json = is_json + self.model_view = model_view self.serialized_args = {} self.url_args = {} @@ -169,22 +170,23 @@ class ViewContext(object): self.should_redirect_at_end = not is_json self.template = None self.template_ctx = {} - self.model_view = None self.redirect_next = None -def create_view(model_view, view_context, is_login_required=False, the_roles_required=None, **kwargs): - view_context.model_view = model_view +def return_json_or_template(view_context): + if view_context.is_json: + return view_context.jsonify_func(view_context) + view_context.template_func(view_context) + view_context.template_ctx_func(view_context) + return view_context.render_func(view_context) + + +def create_view(model_view, view_context_kwargs, is_login_required=False, the_roles_required=None, **kwargs): + view_context_kwargs['model_view'] = model_view the_roles_required = [] if not the_roles_required else the_roles_required - def return_json_or_template(): - if view_context.is_json: - return view_context.jsonify_func(view_context) - view_context.template_func(view_context) - view_context.template_ctx_func(view_context) - return view_context.render_func(view_context) - def inner(**kwargs): + view_context = ViewContext(**view_context_kwargs) view_context.url_args = kwargs view_context.args_get_func(view_context) view_context.args_process_func(view_context) @@ -195,7 +197,7 @@ def create_view(model_view, view_context, is_login_required=False, the_roles_req return view_context.redirect_func(view_context) if request.method == "GET": - return return_json_or_template() + return return_json_or_template(view_context) view_context.should_execute_func(view_context) if not view_context.should_execute: @@ -213,7 +215,7 @@ def create_view(model_view, view_context, is_login_required=False, the_roles_req if view_context.should_redirect_at_end: return view_context.redirect_func(view_context) - return return_json_or_template() + return return_json_or_template(view_context) if is_login_required: if the_roles_required: inner = roles_required(*the_roles_required)(inner) @@ -243,12 +245,14 @@ class ModelView(object): endpoint = url_args.pop('endpoint') api_endpoint = 'api_{}'.format(endpoint) view_func = url_args.pop('view_func') + view_context_kwargs = copy(kwargs['view_context'].__dict__) + kwargs['view_context_kwargs'] = view_context_kwargs self.app.add_url_rule(rule=url, endpoint=endpoint, view_func=view_func(self, **kwargs), **url_args) view_context_kwargs = copy(kwargs['view_context'].__dict__) view_context_kwargs['is_json'] = True - kwargs['view_context'] = ViewContext(**view_context_kwargs) + kwargs['view_context_kwargs'] = view_context_kwargs self.app.add_url_rule(rule=api_url, endpoint=api_endpoint, view_func=view_func(self, **kwargs), **url_args) diff --git a/provision/provision_app/app.py b/provision/provision_app/app.py new file mode 100644 index 0000000..78e6982 --- /dev/null +++ b/provision/provision_app/app.py @@ -0,0 +1,24 @@ +import json + +from flask import Flask, render_template, request, jsonify + +app = Flask(__name__) + + +@app.route('/') +def home(): + return render_template("bootstrap.html") + + +@app.route('/config', methods=["post"]) +def post_config(): + config = json.loads(request.form) + + return jsonify( + { + "raw": config, + }) + + +if __name__ == "__main__": + app.run(debug=True, port=4999) diff --git a/provision/provision_app/templates/bootstrap.html b/provision/provision_app/templates/bootstrap.html new file mode 100644 index 0000000..6ccbb9c --- /dev/null +++ b/provision/provision_app/templates/bootstrap.html @@ -0,0 +1,98 @@ +

New project

+
+

Project name: +

Project path: +

Development

+ + Local machine
+ This will install all required system packages on your local machine and all python packages in a virtual environment +

+ + Docker containers
+ This will install docker on your local machine and start containers for development +

+ + Using Vagrant + Virtualbox
+ This will create a virtual machine on your machine +

+ +

Production environment

+ + Using systemd services + nginx
+ This will create systemd services and nginx as reverse proxy +

+ + Docker containers
+ This will create docker containers for all services +

+ + Using Kubernetes
+ This will create pods, deployments and other k8s objects for your services +
+ + SSL for development
+ +

Components

+

Back end

+
+ +
+ Database | type +
+ Authentication
+ Workers and Queue | type +
+ Scheduling | type: celery beat
+ Search +
+ Translations
+ Limiter
+ Caching
+

Management

+ Debugtoolbar for development
+ Database managemt | type: pgadmin
+ Workers managemt | type: flower
+ Queue managemt | type: rabbitmq-mgmt
+ Admin webapp
+ Monitoring | type: monit
+ Error tracking | type: sentry
+
+

Front end

+

JS: + Jquery
+ Chosen
+ Datatables
+ Fuse (front-end search)
+ Draggable
+ Lightbox
+ Autocomplete JS
+ Backbone JS
+ CRUDy
+

CSS: +
+ Font Awesome
+ Websockets
+


+ Gravatar Enabled
+
+ +

+