Posts

Showing posts from March, 2020

Prettify Login page with SLDS

Image
Login form is constructed with plain html at this moment. I'm going to update it with SLDS styles. For our purposes we need styles for Form Elements (like input and checkbox), Box , Button, Alert and Grid to align form properly. All these elements can be found here https://www.lightningdesignsystem.com/ ./backend/templates/auth/login.html {% extends "_base.html" %} {% block content %} <div> <div class="slds-box slds-size_2-of-3 slds-medium-size_1-of-2 slds-large-size_1-of-3 c-login-box"> <h2>Login</h2> <div> {% with messages = get_flashed_messages() %} {% if messages %} <div class="slds-notify slds-notify_alert slds-theme_alert-texture slds-theme_warning" role="alert"> <span class="slds-assistive-text">warning</span> <span class="slds-icon_contai

Move footer to the bottom of the page

Image
At this moment our footer is right after main content. For short pages it looks ugly. Let's fix it. As footer is inside base template we need to add css styles to the global.css file in ./backend/static html, body { background-color: #F3F3F4; height: 100%; } .main-wrapper { min-height: 100%; height: auto !important; margin: 0 auto -35px; } footer { clear: both; height: 35px; background-color: #fff; } .c-footer-content { padding-top: 5px; } and base template itself should have this structure <body> <div class="main-wrapper"> <div class="c-header"> ... </div> <div class="c-body"> {% block content %}{% endblock %} </div> </div> <footer style="text-align: center;"> <div class="c-footer-content"> <p>&copy; 2020 - Salesforce Backup

Communication between Backend and Frontend

Image
The main gateway between our Frontend (Angular) app and Backend (Flask) will controllers that should accept GET and POST with JSON payload HTTP request and return response in JSON format. In common we need to implement REST API for our Frontend. In other case in Frontend we should create special service to manage all requests to this API. Let's create dummy endpoint to get test list of fake data from Backend. Create new blueprint controller for our test purposes ./backend/controllers/test.py and add simple method to handle GET request from Angular from datetime import datetime from datetime import date from flask import Blueprint, jsonify, request from flask_login import login_required from flask_login import current_user from models import User from sqlalchemy.orm import defer # load_only test_bp = Blueprint('test', __name__, url_prefix='/test') @test_bp.route('/', methods=['GET']) @login_required def get_test_data(): arg0 = reque

Auth menu in Base template

Image
Some things we need to see in all pages are global navigation and information and links from authentication system. Let's create second one. With Flask-Login it is pretty simple. It offers us  current_user   variable accessible in all templates. To show current user information in all pages we need to modify our base template. Here is a part of code I've added to header and with some style improvements. ... <div class="c-header"> <div class="slds-grid"> <div class="slds-col"> <span class="slds-icon_container slds-icon-custom-custom5" title="Description of icon when needed"> <svg style="width: 50px; height:50px;" class="slds-icon" aria-hidden="true"> <use xlink:href="/static/slds/icons/custom-sprite/svg/symbols.svg#custom5"></use&g

Salesforce Lightning Design System (SLDS)

Image
At this moment our UI looks ugly without any styles. To make it looks better we can to use any of existing CSS frameworks. I tried Bootstrap ( https://getbootstrap.com/ ), Foundation ( https://get.foundation/ ), UIkit ( https://getuikit.com/ ). But as a Salesforce developer I found SLDS ( https://www.lightningdesignsystem.com/ ) is closer to my heart. Let's add it to our project. Download last SLDS (current version is 2.11.6) from https://www.lightningdesignsystem.com/downloads/ Extract it to the ./backend/static/slds folder. There are few other ways to add SLDS to the project: - from NPM in the Angular subproject. But in this case it can be accessible by Angular only and is compiled as part of the result bundle. But we have Flask project as global playground and few pages (like /auth/login) should work out of the angular context but have the same look. - external CDN (like  https://cdnjs.com/ ). I like this approach and use it often during development time, but in ca

Base template

Image
Usually regular sites have parts of the page shared between all pages. It can be header, footer, head block with required page setup information, main menu and auth section. Jinja templating system should help us to implement it. First of all let's remove standard Angular Page generated for new project. We don't need this nice page anymore. Let's replace it with simple placeholder. ./frontend/src/app/app.component.html <div> <h1>Angular APP</h1> </div> In ./templates folder we need to create new file with base template ./backend/templates/_base.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Salesforce Backup Service</title> {% block header %}{% endblock %} </head> <body> <div class="main-wrapper"> <div cl

User authentification with Flask-Login

Image
One important step of project preparation is Security. We plan to publish our app to Heroku where it will be accessible by anyone in the world. Let's make it more secure with Flask-Login ( https://flask-login.readthedocs.io/en/latest/ ). There is one post I will follow. https://www.digitalocean.com/community/tutorials/how-to-add-authentication-to-your-app-with-flask-login But I will simplify it and will use login flow only at this moment as we don't need registration. But for new user creation I will add cli script. To add auth flow to our app we need to create Login View with Controller and some additional service methods for Flask-Login. Also we have to update User model a little bit. backend/models/user.py from models import db from flask_login import UserMixin class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(255), unique=True, nullable=False) email

Prettify project structure with Blueprints

We started already with project structure optimization - DB models are stored in separate folder and files. Templates also looks good. But route handlers (controllers) are still in app.py file. It is bad practice, let's fix it. Flask offers us nice solution -  Blueprints ( https://flask.palletsprojects.com/en/1.0.x/blueprints/ ) Let's move our home and test hello controllers to  ./controllers/default.py folder. default.py import os import json from flask import Blueprint, render_template from models import User default = Blueprint('default', __name__) @default.route('/hello') def hello_world(): return 'Hello, World!' @default.route('/') def home(): users = User.query.all() print('Users: ', users) is_development_mode = os.environ.get('FLASK_ENV', 'production') == 'development' if is_development_mode: return render_template('home.html', is_development_mode=is_devel

Setup DB (Postgres)

Image
During my programming career I used many different DBs. It was relational and nosql DBs. I liked nosql due to schema free approach. It is perfect for fast prototypes development and in small projects, but in long term it causes many hidden problems with project management. With JSONB field type Postgres becomes a real Grail in DB world. With all power of regular relational DB it has option to store and process schema-free data. It is perfect alliance. Let's add Postgres to our DB. Moreover this DB has free plan in Heroku ( https://elements.heroku.com/addons/heroku-postgresql ), so we can start with our small Production easily. One more thing related to DB in our project will be ORM - SQLAlchemy it the best solution I used in different python projects and this time not an exception. SQLAlchemy https://www.sqlalchemy.org/ Flask-SQLAlchemy https://flask-sqlalchemy.palletsprojects.com/en/2.x/ Life-Hack for setup and run different types of DB or any other tools required for yo

Build Angular frontend to static resource in Flask (with few hacks)

Image
Last time ( https://angular-python-salesforce.blogspot.com/2020/03/join-flask-and-angular-into-one-project.html ) we join backend and frontend in Development Mode. But in Production Mode Flask still returns us blank page. Let's fix that. In Production Mode we don't have angular dev server in localhost:4200. Instead we should use compiled frontend bundle from Flask Static Resources. We need to build our frontend but not with a standard way. First of all update "build" in package.json with this value: "build": "cd ./frontend && ng build --prod --base-href / --deploy-url /static/app/ --output-path ../backend/static/app && node ../deploy/generate_index_json.js" all looks simple according to standard Angular Docs except last part. Here generate_index_json.js is our custom script that patches build results to make it friendly for latter use from Flask. generate_index_json.js: const fs = require('fs'); console.log(

HTTPS in local environment for Angular + Flask project.

Image
Sometimes it is important to run project in local environment with HTTPS. For example when you use third party authentication system in our app. In my case I prefer to have local instance similar as mush as possible to the production. Moreover, it’s easy to implement. First what you need is the ssl key. You can follow this article to create it https://devcenter.heroku.com/articles/ssl-certificate-self Create your ssl key in ./key project folder. Finally it should look like this [dmnbrest@~/Documents/myPython/blog2/project/key]$ ls server.crt server.csr server.key Add HTTPS support to the FLASK: Update init section in your backend server file ( ./backend/app.py ) this way if __name__ == "__main__":     context = ('./key/server.crt', './key/server.key')     app.run(ssl_context=context, host='0.0.0.0', debug=True) But now we need to run backend with other command python ./backend/app.py This time you should see this output in

Join Flask and Angular into one project

Image
In last post  Flask + Angular base project  we created two separate subprojects for Frontend and Backend . Now we need to make it work as one solid application. Frontent should work with Flask context and Flask should be able manage frontend as part of views. At this moment we go away from official documentation and start to build nice developer environment. 1. First we need to create Flask home view with frontend management magic. This view is our application entry point -  https://flask.palletsprojects.com/en/1.1.x/quickstart/#rendering-templates - Create new folder ./templates with home.html within. <h1>Hello!</h1> <p>This is test variable: {{var_1}}</p> - Modify app.py to look it this way: from flask import Flask, render_template app = Flask(__name__) @app.route('/hello') def hello_world(): return 'Hello, World!' @app.route('/') def home(): var_1 = 'Test Me!' return render_template('home.htm