From 3b5cf0ab46ec0732dda085a307832dd0eebd2ea4 Mon Sep 17 00:00:00 2001 From: Christina <206peacegypsy@gmail.com> Date: Mon, 12 Jul 2021 15:09:53 -0700 Subject: [PATCH 01/19] initial setup and add models --- app/__init__.py | 5 +- app/models.card.py | 0 app/models/__init__.py | 28 ++++++ app/models/board.py | 5 + app/models/card.py | 5 + migrations/README | 1 + migrations/alembic.ini | 45 +++++++++ migrations/env.py | 96 +++++++++++++++++++ migrations/script.py.mako | 24 +++++ .../versions/0998518428e5_adding_models.py | 87 +++++++++++++++++ node_modules/.yarn-integrity | 10 ++ yarn.lock | 4 + 12 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 app/models.card.py create mode 100644 migrations/README create mode 100644 migrations/alembic.ini create mode 100644 migrations/env.py create mode 100644 migrations/script.py.mako create mode 100644 migrations/versions/0998518428e5_adding_models.py create mode 100644 node_modules/.yarn-integrity create mode 100644 yarn.lock diff --git a/app/__init__.py b/app/__init__.py index 1c821436..752fb975 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -17,8 +17,9 @@ def create_app(): app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get( "SQLALCHEMY_DATABASE_URI") - # Import models here for Alembic setup - # from app.models.ExampleModel import ExampleModel + + from app.models.board import Board + from app.models.card import Card db.init_app(app) migrate.init_app(app, db) diff --git a/app/models.card.py b/app/models.card.py new file mode 100644 index 00000000..e69de29b diff --git a/app/models/__init__.py b/app/models/__init__.py index e69de29b..481bb284 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -0,0 +1,28 @@ +from flask import Flask +from flask_sqlalchemy import SQLAlchemy +from flask_migrate import Migrate +from dotenv import load_dotenv +import os + +db = SQLAlchemy() +migrate = Migrate() +load_dotenv() + + +def create_app(test_config=None): + app = Flask(__name__) + + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get( + "SQLALCHEMY_DATABASE_URI") + + db.init_app(app) + migrate.init_app(app, db) + + # from app.models.planet import Planet + + + # from .routes import planets_bp + # app.register_blueprint(planets_bp) + + return app \ No newline at end of file diff --git a/app/models/board.py b/app/models/board.py index 147eb748..c7c454be 100644 --- a/app/models/board.py +++ b/app/models/board.py @@ -1 +1,6 @@ from app import db + +class Board(db.Model): + board_id = db.Column(db.Integer, primary_key=True, autoincrement=True) + title = db.Column(db.String) + owner = db.Column(db.String) \ No newline at end of file diff --git a/app/models/card.py b/app/models/card.py index 147eb748..bec509cd 100644 --- a/app/models/card.py +++ b/app/models/card.py @@ -1 +1,6 @@ from app import db + +class Card (db.Model): + card_id = db.Column(db.Integer, primary_key=True, autoincrement=True) + message = db.Column(db.String) + likes_count = db.Column(db.Integer) \ No newline at end of file diff --git a/migrations/README b/migrations/README new file mode 100644 index 00000000..98e4f9c4 --- /dev/null +++ b/migrations/README @@ -0,0 +1 @@ +Generic single-database configuration. \ No newline at end of file diff --git a/migrations/alembic.ini b/migrations/alembic.ini new file mode 100644 index 00000000..f8ed4801 --- /dev/null +++ b/migrations/alembic.ini @@ -0,0 +1,45 @@ +# A generic, single database configuration. + +[alembic] +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/migrations/env.py b/migrations/env.py new file mode 100644 index 00000000..8b3fb335 --- /dev/null +++ b/migrations/env.py @@ -0,0 +1,96 @@ +from __future__ import with_statement + +import logging +from logging.config import fileConfig + +from sqlalchemy import engine_from_config +from sqlalchemy import pool +from flask import current_app + +from alembic import context + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) +logger = logging.getLogger('alembic.env') + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +config.set_main_option( + 'sqlalchemy.url', + str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%')) +target_metadata = current_app.extensions['migrate'].db.metadata + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True + ) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + + # this callback is used to prevent an auto-migration from being generated + # when there are no changes to the schema + # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html + def process_revision_directives(context, revision, directives): + if getattr(config.cmd_opts, 'autogenerate', False): + script = directives[0] + if script.upgrade_ops.is_empty(): + directives[:] = [] + logger.info('No changes in schema detected.') + + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix='sqlalchemy.', + poolclass=pool.NullPool, + ) + + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata, + process_revision_directives=process_revision_directives, + **current_app.extensions['migrate'].configure_args + ) + + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/migrations/script.py.mako b/migrations/script.py.mako new file mode 100644 index 00000000..2c015630 --- /dev/null +++ b/migrations/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/migrations/versions/0998518428e5_adding_models.py b/migrations/versions/0998518428e5_adding_models.py new file mode 100644 index 00000000..1049c869 --- /dev/null +++ b/migrations/versions/0998518428e5_adding_models.py @@ -0,0 +1,87 @@ +"""adding models + +Revision ID: 0998518428e5 +Revises: +Create Date: 2021-07-12 15:09:07.865089 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '0998518428e5' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('board', + sa.Column('board_id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('title', sa.String(), nullable=True), + sa.Column('owner', sa.String(), nullable=True), + sa.PrimaryKeyConstraint('board_id') + ) + op.create_table('card', + sa.Column('card_id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('message', sa.String(), nullable=True), + sa.Column('likes_count', sa.Integer(), nullable=True), + sa.PrimaryKeyConstraint('card_id') + ) + op.drop_table('hotel_guests') + op.drop_table('flowers') + op.drop_table('reviews') + op.drop_table('tags') + op.drop_table('posts') + op.drop_table('posts_tags') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('posts_tags', + sa.Column('post_id', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('tag_id', sa.INTEGER(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['post_id'], ['posts.id'], name='posts_tags_post_id_fkey'), + sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], name='posts_tags_tag_id_fkey'), + sa.PrimaryKeyConstraint('post_id', 'tag_id', name='posts_tags_pkey') + ) + op.create_table('posts', + sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('title', sa.VARCHAR(length=64), autoincrement=False, nullable=True), + sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name='posts_pkey') + ) + op.create_table('tags', + sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('tagname', sa.VARCHAR(length=64), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name='tags_pkey') + ) + op.create_table('reviews', + sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('title', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + sa.Column('product_id', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), + sa.Column('creator_id', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('stars', sa.INTEGER(), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name='reviews_pkey') + ) + op.create_table('flowers', + sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('name', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + sa.Column('soil_type', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + sa.Column('light_level', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + sa.Column('season', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name='flowers_pkey') + ) + op.create_table('hotel_guests', + sa.Column('guest_id', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('guest_name', sa.VARCHAR(length=200), autoincrement=False, nullable=True), + sa.Column('is_checked_in', sa.BOOLEAN(), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('guest_id', name='hotel_guests_pkey') + ) + op.drop_table('card') + op.drop_table('board') + # ### end Alembic commands ### diff --git a/node_modules/.yarn-integrity b/node_modules/.yarn-integrity new file mode 100644 index 00000000..0f19eb7a --- /dev/null +++ b/node_modules/.yarn-integrity @@ -0,0 +1,10 @@ +{ + "systemParams": "darwin-x64-83", + "modulesFolders": [], + "flags": [], + "linkedModules": [], + "topLevelPatterns": [], + "lockfileEntries": {}, + "files": [], + "artifacts": {} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..fb57ccd1 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + From 3e9d2fb9cb33b6c8fdbb6af3d0be3067076456ca Mon Sep 17 00:00:00 2001 From: Christina <206peacegypsy@gmail.com> Date: Mon, 12 Jul 2021 16:21:50 -0700 Subject: [PATCH 02/19] fixed error in db --- .../versions/0998518428e5_adding_models.py | 158 +++++++++--------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/migrations/versions/0998518428e5_adding_models.py b/migrations/versions/0998518428e5_adding_models.py index 1049c869..12094273 100644 --- a/migrations/versions/0998518428e5_adding_models.py +++ b/migrations/versions/0998518428e5_adding_models.py @@ -1,87 +1,87 @@ -"""adding models +# """adding models -Revision ID: 0998518428e5 -Revises: -Create Date: 2021-07-12 15:09:07.865089 +# Revision ID: 0998518428e5 +# Revises: +# Create Date: 2021-07-12 15:09:07.865089 -""" -from alembic import op -import sqlalchemy as sa +# """ +# from alembic import op +# import sqlalchemy as sa -# revision identifiers, used by Alembic. -revision = '0998518428e5' -down_revision = None -branch_labels = None -depends_on = None +# # revision identifiers, used by Alembic. +# revision = '0998518428e5' +# down_revision = None +# branch_labels = None +# depends_on = None -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('board', - sa.Column('board_id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('title', sa.String(), nullable=True), - sa.Column('owner', sa.String(), nullable=True), - sa.PrimaryKeyConstraint('board_id') - ) - op.create_table('card', - sa.Column('card_id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('message', sa.String(), nullable=True), - sa.Column('likes_count', sa.Integer(), nullable=True), - sa.PrimaryKeyConstraint('card_id') - ) - op.drop_table('hotel_guests') - op.drop_table('flowers') - op.drop_table('reviews') - op.drop_table('tags') - op.drop_table('posts') - op.drop_table('posts_tags') - # ### end Alembic commands ### +# def upgrade(): +# # ### commands auto generated by Alembic - please adjust! ### +# op.create_table('board', +# sa.Column('board_id', sa.Integer(), autoincrement=True, nullable=False), +# sa.Column('title', sa.String(), nullable=True), +# sa.Column('owner', sa.String(), nullable=True), +# sa.PrimaryKeyConstraint('board_id') +# ) +# op.create_table('card', +# sa.Column('card_id', sa.Integer(), autoincrement=True, nullable=False), +# sa.Column('message', sa.String(), nullable=True), +# sa.Column('likes_count', sa.Integer(), nullable=True), +# sa.PrimaryKeyConstraint('card_id') +# ) +# op.drop_table('hotel_guests') +# op.drop_table('flowers') +# op.drop_table('reviews') +# op.drop_table('tags') +# op.drop_table('posts') +# op.drop_table('posts_tags') +# # ### end Alembic commands ### -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('posts_tags', - sa.Column('post_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('tag_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.ForeignKeyConstraint(['post_id'], ['posts.id'], name='posts_tags_post_id_fkey'), - sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], name='posts_tags_tag_id_fkey'), - sa.PrimaryKeyConstraint('post_id', 'tag_id', name='posts_tags_pkey') - ) - op.create_table('posts', - sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('title', sa.VARCHAR(length=64), autoincrement=False, nullable=True), - sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), - sa.PrimaryKeyConstraint('id', name='posts_pkey') - ) - op.create_table('tags', - sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('tagname', sa.VARCHAR(length=64), autoincrement=False, nullable=True), - sa.PrimaryKeyConstraint('id', name='tags_pkey') - ) - op.create_table('reviews', - sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('title', sa.VARCHAR(length=32), autoincrement=False, nullable=True), - sa.Column('product_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), - sa.Column('creator_id', sa.INTEGER(), autoincrement=False, nullable=True), - sa.Column('stars', sa.INTEGER(), autoincrement=False, nullable=True), - sa.PrimaryKeyConstraint('id', name='reviews_pkey') - ) - op.create_table('flowers', - sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('name', sa.VARCHAR(length=32), autoincrement=False, nullable=True), - sa.Column('soil_type', sa.VARCHAR(length=32), autoincrement=False, nullable=True), - sa.Column('light_level', sa.VARCHAR(length=32), autoincrement=False, nullable=True), - sa.Column('season', sa.VARCHAR(length=32), autoincrement=False, nullable=True), - sa.PrimaryKeyConstraint('id', name='flowers_pkey') - ) - op.create_table('hotel_guests', - sa.Column('guest_id', sa.INTEGER(), autoincrement=False, nullable=False), - sa.Column('guest_name', sa.VARCHAR(length=200), autoincrement=False, nullable=True), - sa.Column('is_checked_in', sa.BOOLEAN(), autoincrement=False, nullable=True), - sa.PrimaryKeyConstraint('guest_id', name='hotel_guests_pkey') - ) - op.drop_table('card') - op.drop_table('board') - # ### end Alembic commands ### +# def downgrade(): +# # ### commands auto generated by Alembic - please adjust! ### +# op.create_table('posts_tags', +# sa.Column('post_id', sa.INTEGER(), autoincrement=False, nullable=False), +# sa.Column('tag_id', sa.INTEGER(), autoincrement=False, nullable=False), +# sa.ForeignKeyConstraint(['post_id'], ['posts.id'], name='posts_tags_post_id_fkey'), +# sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], name='posts_tags_tag_id_fkey'), +# sa.PrimaryKeyConstraint('post_id', 'tag_id', name='posts_tags_pkey') +# ) +# op.create_table('posts', +# sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), +# sa.Column('title', sa.VARCHAR(length=64), autoincrement=False, nullable=True), +# sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), +# sa.PrimaryKeyConstraint('id', name='posts_pkey') +# ) +# op.create_table('tags', +# sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), +# sa.Column('tagname', sa.VARCHAR(length=64), autoincrement=False, nullable=True), +# sa.PrimaryKeyConstraint('id', name='tags_pkey') +# ) +# op.create_table('reviews', +# sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), +# sa.Column('title', sa.VARCHAR(length=32), autoincrement=False, nullable=True), +# sa.Column('product_id', sa.INTEGER(), autoincrement=False, nullable=True), +# sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), +# sa.Column('creator_id', sa.INTEGER(), autoincrement=False, nullable=True), +# sa.Column('stars', sa.INTEGER(), autoincrement=False, nullable=True), +# sa.PrimaryKeyConstraint('id', name='reviews_pkey') +# ) +# op.create_table('flowers', +# sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), +# sa.Column('name', sa.VARCHAR(length=32), autoincrement=False, nullable=True), +# sa.Column('soil_type', sa.VARCHAR(length=32), autoincrement=False, nullable=True), +# sa.Column('light_level', sa.VARCHAR(length=32), autoincrement=False, nullable=True), +# sa.Column('season', sa.VARCHAR(length=32), autoincrement=False, nullable=True), +# sa.PrimaryKeyConstraint('id', name='flowers_pkey') +# ) +# op.create_table('hotel_guests', +# sa.Column('guest_id', sa.INTEGER(), autoincrement=False, nullable=False), +# sa.Column('guest_name', sa.VARCHAR(length=200), autoincrement=False, nullable=True), +# sa.Column('is_checked_in', sa.BOOLEAN(), autoincrement=False, nullable=True), +# sa.PrimaryKeyConstraint('guest_id', name='hotel_guests_pkey') +# ) +# op.drop_table('card') +# op.drop_table('board') +# # ### end Alembic commands ### From 2a9e7f54aa3b3240e9c3d27802a2b892e58a91e6 Mon Sep 17 00:00:00 2001 From: peacegypsy Date: Tue, 13 Jul 2021 07:15:07 -0700 Subject: [PATCH 03/19] fixed some errors and added get and post for boards --- app/__init__.py | 6 + app/routes.py | 34 ++++ logfile | 24 +++ .../versions/0998518428e5_adding_models.py | 158 +++++++++--------- node_modules/.yarn-integrity | 10 -- 5 files changed, 143 insertions(+), 89 deletions(-) create mode 100644 logfile delete mode 100644 node_modules/.yarn-integrity diff --git a/app/__init__.py b/app/__init__.py index 752fb975..8a24b3ee 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -23,6 +23,12 @@ def create_app(): db.init_app(app) migrate.init_app(app, db) + + from .routes import hello_world_bp + app.register_blueprint(hello_world_bp) + + from .routes import boards_bp + app.register_blueprint(boards_bp) # Register Blueprints here # from .routes import example_bp diff --git a/app/routes.py b/app/routes.py index 480b8c4b..3f6b3cb1 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1,4 +1,38 @@ from flask import Blueprint, request, jsonify, make_response from app import db +from app.models.board import Board +from app.models.card import Card + +boards_bp = Blueprint("boards", __name__, url_prefix="/boards") +hello_world_bp = Blueprint("hello_world", __name__) + +@hello_world_bp.route("/hello-world", methods=["GET"]) +def hello_world(): + my_beautiful_response_body = "Hello, World!" + return my_beautiful_response_body + +@boards_bp.route("", methods=["GET", "POST"]) +def handle_boards(): + if request.method == "GET": + boards = Board.query.all() + boards_response = [] + for board in boards: + boards_response.append({ + "board_id": board.board_id, + "title": board.title, + "owner": board.owner, + }) + return jsonify(boards_response) + elif request.method == "POST": + request_body = request.get_json() + title = request_body.get("title") + owner = request_body.get("owner") + new_board = Board(title=request_body["title"], + owner=request_body["owner"]) + + db.session.add(new_board) + db.session.commit() + + return make_response(f"Board {new_board.title} successfully created", 201) # example_bp = Blueprint('example_bp', __name__) diff --git a/logfile b/logfile new file mode 100644 index 00000000..82681fb1 --- /dev/null +++ b/logfile @@ -0,0 +1,24 @@ +2021-07-13 06:07:34.941 PDT [96833] LOG: starting PostgreSQL 13.3 on x86_64-apple-darwin20.4.0, compiled by Apple clang version 12.0.5 (clang-1205.0.22.9), 64-bit +2021-07-13 06:07:34.942 PDT [96833] LOG: listening on IPv4 address "127.0.0.1", port 5432 +2021-07-13 06:07:34.942 PDT [96833] LOG: listening on IPv6 address "::1", port 5432 +2021-07-13 06:07:34.943 PDT [96833] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432" +2021-07-13 06:07:34.947 PDT [96834] LOG: database system was shut down at 2021-07-13 06:07:20 PDT +2021-07-13 06:07:34.949 PDT [96833] LOG: database system is ready to accept connections +2021-07-13 06:07:46.358 PDT [96866] FATAL: role "postgres" does not exist +2021-07-13 06:08:40.481 PDT [96996] FATAL: database "du" does not exist +2021-07-13 06:09:23.143 PDT [97350] FATAL: role "postgres" does not exist +2021-07-13 06:10:40.468 PDT [97924] FATAL: role "postgres" does not exist +2021-07-13 06:13:27.223 PDT [98323] FATAL: role "postgres" does not exist +2021-07-13 06:19:38.338 PDT [310] FATAL: role "postgres" does not exist +2021-07-13 06:23:44.026 PDT [1012] FATAL: role "postgres" does not exist +2021-07-13 06:23:54.376 PDT [1035] FATAL: database "Xtina206" does not exist +2021-07-13 06:28:43.565 PDT [1965] FATAL: role "postgres" does not exist +2021-07-13 06:32:11.170 PDT [2642] FATAL: role "xtina" is not permitted to log in +2021-07-13 06:32:22.481 PDT [2666] FATAL: database "Xtina206" does not exist +2021-07-13 06:33:39.135 PDT [2911] FATAL: role "postgres" does not exist +2021-07-13 06:33:50.071 PDT [2934] FATAL: database "Xtina206" does not exist +2021-07-13 06:33:59.221 PDT [2957] FATAL: database "Xtina206" does not exist +2021-07-13 06:34:16.502 PDT [3001] FATAL: role "inspiration_board_development" does not exist +2021-07-13 06:34:26.178 PDT [3025] FATAL: role "postgres" does not exist +2021-07-13 06:34:35.779 PDT [3049] FATAL: database "Xtina206" does not exist +2021-07-13 06:34:57.264 PDT [3095] FATAL: role "postgres" does not exist diff --git a/migrations/versions/0998518428e5_adding_models.py b/migrations/versions/0998518428e5_adding_models.py index 12094273..70ad956d 100644 --- a/migrations/versions/0998518428e5_adding_models.py +++ b/migrations/versions/0998518428e5_adding_models.py @@ -1,87 +1,87 @@ -# """adding models +"""adding models -# Revision ID: 0998518428e5 -# Revises: -# Create Date: 2021-07-12 15:09:07.865089 +Revision ID: 0998518428e5 +Revises: +Create Date: 2021-07-12 15:09:07.865089 -# """ -# from alembic import op -# import sqlalchemy as sa +""" +from alembic import op +import sqlalchemy as sa -# # revision identifiers, used by Alembic. -# revision = '0998518428e5' -# down_revision = None -# branch_labels = None -# depends_on = None +# revision identifiers, used by Alembic. +revision = '0998518428e5' +down_revision = None +branch_labels = None +depends_on = None -# def upgrade(): -# # ### commands auto generated by Alembic - please adjust! ### -# op.create_table('board', -# sa.Column('board_id', sa.Integer(), autoincrement=True, nullable=False), -# sa.Column('title', sa.String(), nullable=True), -# sa.Column('owner', sa.String(), nullable=True), -# sa.PrimaryKeyConstraint('board_id') -# ) -# op.create_table('card', -# sa.Column('card_id', sa.Integer(), autoincrement=True, nullable=False), -# sa.Column('message', sa.String(), nullable=True), -# sa.Column('likes_count', sa.Integer(), nullable=True), -# sa.PrimaryKeyConstraint('card_id') -# ) -# op.drop_table('hotel_guests') -# op.drop_table('flowers') -# op.drop_table('reviews') -# op.drop_table('tags') -# op.drop_table('posts') -# op.drop_table('posts_tags') -# # ### end Alembic commands ### +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('board', + sa.Column('board_id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('title', sa.String(), nullable=True), + sa.Column('owner', sa.String(), nullable=True), + sa.PrimaryKeyConstraint('board_id') + ) + op.create_table('card', + sa.Column('card_id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('message', sa.String(), nullable=True), + sa.Column('likes_count', sa.Integer(), nullable=True), + sa.PrimaryKeyConstraint('card_id') + ) + # op.drop_table('hotel_guests') + # op.drop_table('flowers') + # op.drop_table('reviews') + # op.drop_table('tags') + # op.drop_table('posts') + # op.drop_table('posts_tags') + # ### end Alembic commands ### -# def downgrade(): -# # ### commands auto generated by Alembic - please adjust! ### -# op.create_table('posts_tags', -# sa.Column('post_id', sa.INTEGER(), autoincrement=False, nullable=False), -# sa.Column('tag_id', sa.INTEGER(), autoincrement=False, nullable=False), -# sa.ForeignKeyConstraint(['post_id'], ['posts.id'], name='posts_tags_post_id_fkey'), -# sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], name='posts_tags_tag_id_fkey'), -# sa.PrimaryKeyConstraint('post_id', 'tag_id', name='posts_tags_pkey') -# ) -# op.create_table('posts', -# sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), -# sa.Column('title', sa.VARCHAR(length=64), autoincrement=False, nullable=True), -# sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), -# sa.PrimaryKeyConstraint('id', name='posts_pkey') -# ) -# op.create_table('tags', -# sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), -# sa.Column('tagname', sa.VARCHAR(length=64), autoincrement=False, nullable=True), -# sa.PrimaryKeyConstraint('id', name='tags_pkey') -# ) -# op.create_table('reviews', -# sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), -# sa.Column('title', sa.VARCHAR(length=32), autoincrement=False, nullable=True), -# sa.Column('product_id', sa.INTEGER(), autoincrement=False, nullable=True), -# sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), -# sa.Column('creator_id', sa.INTEGER(), autoincrement=False, nullable=True), -# sa.Column('stars', sa.INTEGER(), autoincrement=False, nullable=True), -# sa.PrimaryKeyConstraint('id', name='reviews_pkey') -# ) -# op.create_table('flowers', -# sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), -# sa.Column('name', sa.VARCHAR(length=32), autoincrement=False, nullable=True), -# sa.Column('soil_type', sa.VARCHAR(length=32), autoincrement=False, nullable=True), -# sa.Column('light_level', sa.VARCHAR(length=32), autoincrement=False, nullable=True), -# sa.Column('season', sa.VARCHAR(length=32), autoincrement=False, nullable=True), -# sa.PrimaryKeyConstraint('id', name='flowers_pkey') -# ) -# op.create_table('hotel_guests', -# sa.Column('guest_id', sa.INTEGER(), autoincrement=False, nullable=False), -# sa.Column('guest_name', sa.VARCHAR(length=200), autoincrement=False, nullable=True), -# sa.Column('is_checked_in', sa.BOOLEAN(), autoincrement=False, nullable=True), -# sa.PrimaryKeyConstraint('guest_id', name='hotel_guests_pkey') -# ) -# op.drop_table('card') -# op.drop_table('board') -# # ### end Alembic commands ### +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + # op.create_table('posts_tags', + # sa.Column('post_id', sa.INTEGER(), autoincrement=False, nullable=False), + # sa.Column('tag_id', sa.INTEGER(), autoincrement=False, nullable=False), + # sa.ForeignKeyConstraint(['post_id'], ['posts.id'], name='posts_tags_post_id_fkey'), + # sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], name='posts_tags_tag_id_fkey'), + # sa.PrimaryKeyConstraint('post_id', 'tag_id', name='posts_tags_pkey') + # ) + # op.create_table('posts', + # sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), + # sa.Column('title', sa.VARCHAR(length=64), autoincrement=False, nullable=True), + # sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), + # sa.PrimaryKeyConstraint('id', name='posts_pkey') + # ) + # op.create_table('tags', + # sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), + # sa.Column('tagname', sa.VARCHAR(length=64), autoincrement=False, nullable=True), + # sa.PrimaryKeyConstraint('id', name='tags_pkey') + # ) + # op.create_table('reviews', + # sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), + # sa.Column('title', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + # sa.Column('product_id', sa.INTEGER(), autoincrement=False, nullable=True), + # sa.Column('body', sa.TEXT(), autoincrement=False, nullable=True), + # sa.Column('creator_id', sa.INTEGER(), autoincrement=False, nullable=True), + # sa.Column('stars', sa.INTEGER(), autoincrement=False, nullable=True), + # sa.PrimaryKeyConstraint('id', name='reviews_pkey') + # ) + # op.create_table('flowers', + # sa.Column('id', sa.INTEGER(), autoincrement=False, nullable=False), + # sa.Column('name', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + # sa.Column('soil_type', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + # sa.Column('light_level', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + # sa.Column('season', sa.VARCHAR(length=32), autoincrement=False, nullable=True), + # sa.PrimaryKeyConstraint('id', name='flowers_pkey') + # ) + # op.create_table('hotel_guests', + # sa.Column('guest_id', sa.INTEGER(), autoincrement=False, nullable=False), + # sa.Column('guest_name', sa.VARCHAR(length=200), autoincrement=False, nullable=True), + # sa.Column('is_checked_in', sa.BOOLEAN(), autoincrement=False, nullable=True), + # sa.PrimaryKeyConstraint('guest_id', name='hotel_guests_pkey') + # ) + op.drop_table('card') + op.drop_table('board') + # ### end Alembic commands ### diff --git a/node_modules/.yarn-integrity b/node_modules/.yarn-integrity deleted file mode 100644 index 0f19eb7a..00000000 --- a/node_modules/.yarn-integrity +++ /dev/null @@ -1,10 +0,0 @@ -{ - "systemParams": "darwin-x64-83", - "modulesFolders": [], - "flags": [], - "linkedModules": [], - "topLevelPatterns": [], - "lockfileEntries": {}, - "files": [], - "artifacts": {} -} \ No newline at end of file From 1eaf1a4944458585fe3bca5357a6ca114457deec Mon Sep 17 00:00:00 2001 From: peacegypsy Date: Tue, 13 Jul 2021 07:28:55 -0700 Subject: [PATCH 04/19] added update and delete methods to boards --- app/routes.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/app/routes.py b/app/routes.py index 3f6b3cb1..9af92dc3 100644 --- a/app/routes.py +++ b/app/routes.py @@ -35,4 +35,34 @@ def handle_boards(): return make_response(f"Board {new_board.title} successfully created", 201) -# example_bp = Blueprint('example_bp', __name__) +@boards_bp.route("/", methods=["GET", "PUT", "DELETE"]) +def handle_board(board_id): + board = Board.query.get(board_id) + + if request.method == "GET": + if board == None: + return make_response("That board does not exist", 404) + return { + "id": board.id, + "title": board.title, + "owner": board.owner + } + elif request.method == "PUT": + if board == None: + return make_response("Board does not exist", 404) + form_data = request.get_json() + + board.title = form_data["title"] + board.owner = form_data["owner"] + + db.session.commit() + + return make_response(f"Board: {board.title} sucessfully updated.") + + elif request.method == "DELETE": + if board == None: + return make_response("Board does not exist", 404) + db.session.delete(board) + db.session.commit() + return make_response(f"Board: {board.title} sucessfully deleted.") +# example_bp = Blueprint('example_bp', __name__) \ No newline at end of file From c8449038b3bb9e4af8bb8c8c25ef11a14ca20bb3 Mon Sep 17 00:00:00 2001 From: peacegypsy Date: Tue, 13 Jul 2021 07:33:34 -0700 Subject: [PATCH 05/19] fixed a bug --- app/routes.py | 2 +- logfile | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/routes.py b/app/routes.py index 9af92dc3..c43da4bb 100644 --- a/app/routes.py +++ b/app/routes.py @@ -43,7 +43,7 @@ def handle_board(board_id): if board == None: return make_response("That board does not exist", 404) return { - "id": board.id, + "id": board.board_id, "title": board.title, "owner": board.owner } diff --git a/logfile b/logfile index 82681fb1..3170bd99 100644 --- a/logfile +++ b/logfile @@ -22,3 +22,4 @@ 2021-07-13 06:34:26.178 PDT [3025] FATAL: role "postgres" does not exist 2021-07-13 06:34:35.779 PDT [3049] FATAL: database "Xtina206" does not exist 2021-07-13 06:34:57.264 PDT [3095] FATAL: role "postgres" does not exist +2021-07-13 07:30:28.182 PDT [12165] LOG: unexpected EOF on client connection with an open transaction From 22619807786044276e41f9d036af4e095cc4cb20 Mon Sep 17 00:00:00 2001 From: nathalia Date: Tue, 13 Jul 2021 08:43:52 -0700 Subject: [PATCH 06/19] Handling 404 error on Post missing title or owner --- app/routes.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/app/routes.py b/app/routes.py index 9af92dc3..ea2cfb9b 100644 --- a/app/routes.py +++ b/app/routes.py @@ -6,11 +6,13 @@ boards_bp = Blueprint("boards", __name__, url_prefix="/boards") hello_world_bp = Blueprint("hello_world", __name__) + @hello_world_bp.route("/hello-world", methods=["GET"]) def hello_world(): my_beautiful_response_body = "Hello, World!" return my_beautiful_response_body + @boards_bp.route("", methods=["GET", "POST"]) def handle_boards(): if request.method == "GET": @@ -24,21 +26,22 @@ def handle_boards(): }) return jsonify(boards_response) elif request.method == "POST": - request_body = request.get_json() - title = request_body.get("title") - owner = request_body.get("owner") + request_body = request.get_json(force=True) + if "title" or "owner" not in request_body: + return {"details": "Invalid data"}, 400 new_board = Board(title=request_body["title"], owner=request_body["owner"]) - + db.session.add(new_board) db.session.commit() return make_response(f"Board {new_board.title} successfully created", 201) + @boards_bp.route("/", methods=["GET", "PUT", "DELETE"]) def handle_board(board_id): board = Board.query.get(board_id) - + if request.method == "GET": if board == None: return make_response("That board does not exist", 404) @@ -51,18 +54,18 @@ def handle_board(board_id): if board == None: return make_response("Board does not exist", 404) form_data = request.get_json() - + board.title = form_data["title"] board.owner = form_data["owner"] - + db.session.commit() - + return make_response(f"Board: {board.title} sucessfully updated.") - + elif request.method == "DELETE": if board == None: return make_response("Board does not exist", 404) db.session.delete(board) db.session.commit() return make_response(f"Board: {board.title} sucessfully deleted.") -# example_bp = Blueprint('example_bp', __name__) \ No newline at end of file +# example_bp = Blueprint('example_bp', __name__) From 8cce624324f171efa105e61a6eef0519b90f4d4b Mon Sep 17 00:00:00 2001 From: peacegypsy Date: Tue, 13 Jul 2021 13:36:13 -0700 Subject: [PATCH 07/19] new branch --- app/routes.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/routes.py b/app/routes.py index c43da4bb..c21dd005 100644 --- a/app/routes.py +++ b/app/routes.py @@ -2,15 +2,29 @@ from app import db from app.models.board import Board from app.models.card import Card +import os +from dotenv import load_dotenv boards_bp = Blueprint("boards", __name__, url_prefix="/boards") hello_world_bp = Blueprint("hello_world", __name__) +load_dotenv() + @hello_world_bp.route("/hello-world", methods=["GET"]) def hello_world(): my_beautiful_response_body = "Hello, World!" return my_beautiful_response_body +# def post_message_to_slack(text): +# SLACK_TOKEN = os.environ.get('SLACKBOT_TOKEN') +# slack_path = "https://slack.com/api/chat.postMessage" +# query_params = { +# 'channel': 'team-duck-yeah', +# 'text': text +# } +# headers = {'Authorization': f"Bearer {SLACK_TOKEN}"} +# request.post(slack_path, params=query_params, headers=headers) + @boards_bp.route("", methods=["GET", "POST"]) def handle_boards(): if request.method == "GET": @@ -65,4 +79,4 @@ def handle_board(board_id): db.session.delete(board) db.session.commit() return make_response(f"Board: {board.title} sucessfully deleted.") -# example_bp = Blueprint('example_bp', __name__) \ No newline at end of file +# example_bp = Blueprint('example_bp', __name__) From 2535fad843d979cc13b0e8a07c988ad82adecc6b Mon Sep 17 00:00:00 2001 From: nathalia Date: Tue, 13 Jul 2021 16:20:57 -0700 Subject: [PATCH 08/19] "Adds function CARD,GET & POST for specific Board" Creates new card function for selected board; Adds a GET all cards of a selected boards; Adds a POST card into a specific board; Adds a handle error for adding a empty message. --- app/__init__.py | 5 ++- app/models/__init__.py | 4 +-- app/models/board.py | 4 ++- app/models/card.py | 5 ++- app/routes.py | 48 +++++++++++++++++++++++++--- migrations/versions/456c575cd4a3_.py | 34 ++++++++++++++++++++ migrations/versions/476dbf543b0b_.py | 30 +++++++++++++++++ 7 files changed, 117 insertions(+), 13 deletions(-) create mode 100644 migrations/versions/456c575cd4a3_.py create mode 100644 migrations/versions/476dbf543b0b_.py diff --git a/app/__init__.py b/app/__init__.py index 8a24b3ee..02b4b0e0 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -17,16 +17,15 @@ def create_app(): app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get( "SQLALCHEMY_DATABASE_URI") - from app.models.board import Board from app.models.card import Card db.init_app(app) migrate.init_app(app, db) - + from .routes import hello_world_bp app.register_blueprint(hello_world_bp) - + from .routes import boards_bp app.register_blueprint(boards_bp) diff --git a/app/models/__init__.py b/app/models/__init__.py index 481bb284..fcd2caea 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -20,9 +20,7 @@ def create_app(test_config=None): migrate.init_app(app, db) # from app.models.planet import Planet - - # from .routes import planets_bp # app.register_blueprint(planets_bp) - return app \ No newline at end of file + return app diff --git a/app/models/board.py b/app/models/board.py index c7c454be..c0a2e9c6 100644 --- a/app/models/board.py +++ b/app/models/board.py @@ -1,6 +1,8 @@ from app import db + class Board(db.Model): board_id = db.Column(db.Integer, primary_key=True, autoincrement=True) title = db.Column(db.String) - owner = db.Column(db.String) \ No newline at end of file + owner = db.Column(db.String) + cards = db.relationship('Card', backref='cards', lazy=True) diff --git a/app/models/card.py b/app/models/card.py index bec509cd..82e137bd 100644 --- a/app/models/card.py +++ b/app/models/card.py @@ -1,6 +1,9 @@ from app import db + class Card (db.Model): card_id = db.Column(db.Integer, primary_key=True, autoincrement=True) message = db.Column(db.String) - likes_count = db.Column(db.Integer) \ No newline at end of file + likes_count = db.Column(db.Integer) + board_id = db.Column(db.Integer, db.ForeignKey( + "board.board_id"), nullable=True) diff --git a/app/routes.py b/app/routes.py index ea2cfb9b..2a4e6867 100644 --- a/app/routes.py +++ b/app/routes.py @@ -26,9 +26,9 @@ def handle_boards(): }) return jsonify(boards_response) elif request.method == "POST": - request_body = request.get_json(force=True) - if "title" or "owner" not in request_body: - return {"details": "Invalid data"}, 400 + request_body = request.get_json() + title = request_body.get("title") + owner = request_body.get("owner") new_board = Board(title=request_body["title"], owner=request_body["owner"]) @@ -46,9 +46,10 @@ def handle_board(board_id): if board == None: return make_response("That board does not exist", 404) return { - "id": board.id, + "id": board.board_id, "title": board.title, - "owner": board.owner + "owner": board.owner, + "cards": board.cards } elif request.method == "PUT": if board == None: @@ -69,3 +70,40 @@ def handle_board(board_id): db.session.commit() return make_response(f"Board: {board.title} sucessfully deleted.") # example_bp = Blueprint('example_bp', __name__) + + +@boards_bp.route("//cards", methods=["POST", "GET"]) +def handle_cards(board_id): + board = Board.query.get(board_id) + + if board is None: + return make_response("", 404) + + if request.method == "GET": + cards = Board.query.get(board_id).cards + cards_response = [] + for card in cards: + cards_response.append({ + "message": card.message + }) + + return make_response( + { + "cards": cards_response + }, 200) + elif request.method == "POST": + request_body = request.get_json() + if 'message' not in request_body: + return {"details": "Invalid data"}, 400 + new_card = Card(message=request_body["message"], + board_id=board_id) + + db.session.add(new_card) + db.session.commit() + + return { + "card": { + "id": new_card.card_id, + "message": new_card.message + } + }, 201 diff --git a/migrations/versions/456c575cd4a3_.py b/migrations/versions/456c575cd4a3_.py new file mode 100644 index 00000000..7c0f7030 --- /dev/null +++ b/migrations/versions/456c575cd4a3_.py @@ -0,0 +1,34 @@ +"""empty message + +Revision ID: 456c575cd4a3 +Revises: 0998518428e5 +Create Date: 2021-07-13 11:00:17.480900 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '456c575cd4a3' +down_revision = '0998518428e5' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('board', sa.Column('card_id', sa.Integer(), nullable=True)) + op.create_foreign_key(None, 'board', 'card', ['card_id'], ['card_id']) + op.add_column('card', sa.Column('board_id', sa.Integer(), nullable=True)) + op.create_foreign_key(None, 'card', 'board', ['board_id'], ['board_id']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'card', type_='foreignkey') + op.drop_column('card', 'board_id') + op.drop_constraint(None, 'board', type_='foreignkey') + op.drop_column('board', 'card_id') + # ### end Alembic commands ### diff --git a/migrations/versions/476dbf543b0b_.py b/migrations/versions/476dbf543b0b_.py new file mode 100644 index 00000000..5397bbf3 --- /dev/null +++ b/migrations/versions/476dbf543b0b_.py @@ -0,0 +1,30 @@ +"""empty message + +Revision ID: 476dbf543b0b +Revises: 456c575cd4a3 +Create Date: 2021-07-13 11:02:51.043402 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '476dbf543b0b' +down_revision = '456c575cd4a3' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint('board_card_id_fkey', 'board', type_='foreignkey') + op.drop_column('board', 'card_id') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('board', sa.Column('card_id', sa.INTEGER(), autoincrement=False, nullable=True)) + op.create_foreign_key('board_card_id_fkey', 'board', 'card', ['card_id'], ['card_id']) + # ### end Alembic commands ### From a645ab4b061b4af0677503f68c124b9d6718038e Mon Sep 17 00:00:00 2001 From: Christina <206peacegypsy@gmail.com> Date: Tue, 13 Jul 2021 21:00:50 -0700 Subject: [PATCH 09/19] branch test --- app/routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routes.py b/app/routes.py index c43da4bb..4352d9a0 100644 --- a/app/routes.py +++ b/app/routes.py @@ -28,7 +28,7 @@ def handle_boards(): title = request_body.get("title") owner = request_body.get("owner") new_board = Board(title=request_body["title"], - owner=request_body["owner"]) + owner=request_body["owner"]) db.session.add(new_board) db.session.commit() From 1cdf7d9f5bcdaced7e9bf94812ad147e83164126 Mon Sep 17 00:00:00 2001 From: peacegypsy Date: Wed, 14 Jul 2021 08:37:02 -0700 Subject: [PATCH 10/19] small tweak --- app/routes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/routes.py b/app/routes.py index bd884e6c..5cc0cd10 100644 --- a/app/routes.py +++ b/app/routes.py @@ -42,7 +42,7 @@ def handle_boards(): title = request_body.get("title") owner = request_body.get("owner") new_board = Board(title=request_body["title"], - owner=request_body["owner"]) + owner=request_body["owner"]) db.session.add(new_board) db.session.commit() @@ -59,7 +59,7 @@ def handle_board(board_id): return { "id": board.board_id, "title": board.title, - "owner": board.owner + "owner": board.owner, } elif request.method == "PUT": if board == None: @@ -79,4 +79,4 @@ def handle_board(board_id): db.session.delete(board) db.session.commit() return make_response(f"Board: {board.title} sucessfully deleted.") -# example_bp = Blueprint('example_bp', __name__) + From 974c9f07dba51708659eac03eb846099c74c37bd Mon Sep 17 00:00:00 2001 From: peacegypsy Date: Wed, 14 Jul 2021 13:10:37 -0700 Subject: [PATCH 11/19] added slackduck functionality and its quacking --- app/routes.py | 29 +++++++++++++++++++---------- logfile | 11 +++++++++++ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/app/routes.py b/app/routes.py index 7b578044..d3234553 100644 --- a/app/routes.py +++ b/app/routes.py @@ -4,6 +4,9 @@ from app.models.card import Card import os from dotenv import load_dotenv +import requests +from slack_sdk import WebClient +from slack_sdk.errors import SlackApiError boards_bp = Blueprint("boards", __name__, url_prefix="/boards") hello_world_bp = Blueprint("hello_world", __name__) @@ -17,15 +20,16 @@ def hello_world(): my_beautiful_response_body = "Hello, World!" return my_beautiful_response_body -# def post_message_to_slack(text): -# SLACK_TOKEN = os.environ.get('SLACKBOT_TOKEN') -# slack_path = "https://slack.com/api/chat.postMessage" -# query_params = { -# 'channel': 'team-duck-yeah', -# 'text': text -# } -# headers = {'Authorization': f"Bearer {SLACK_TOKEN}"} -# request.post(slack_path, params=query_params, headers=headers) +def post_message_to_slack(text): + SLACK_TOKEN = os.environ.get('SLACKBOT_TOKEN') + client = WebClient(token=SLACK_TOKEN) + try: + response = client.chat_postMessage( + channel='C0286U213J5', + text=text + ) + except SlackApiError as e: + assert e.response["error"] @boards_bp.route("", methods=["GET", "POST"]) @@ -48,6 +52,8 @@ def handle_boards(): owner=request_body["owner"]) db.session.add(new_board) db.session.commit() + slack_message = f"Some duck just added a new board!" + post_message_to_slack(slack_message) return make_response(f"Board {new_board.title} successfully created", 201) @@ -63,7 +69,7 @@ def handle_board(board_id): "id": board.board_id, "title": board.title, "owner": board.owner, - "cards": board.cards + #"cards": board.cards } elif request.method == "PUT": if board == None: @@ -109,11 +115,14 @@ def handle_cards(board_id): request_body = request.get_json() if 'message' not in request_body: return {"details": "Invalid data"}, 400 + new_card = Card(message=request_body["message"], board_id=board_id) db.session.add(new_card) db.session.commit() + slack_message = f"Some duck just added a new card!" + post_message_to_slack(slack_message) return { "card": { diff --git a/logfile b/logfile index 3170bd99..3e4a1763 100644 --- a/logfile +++ b/logfile @@ -23,3 +23,14 @@ 2021-07-13 06:34:35.779 PDT [3049] FATAL: database "Xtina206" does not exist 2021-07-13 06:34:57.264 PDT [3095] FATAL: role "postgres" does not exist 2021-07-13 07:30:28.182 PDT [12165] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 08:49:51.995 PDT [64205] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 08:53:28.067 PDT [64292] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 09:05:12.011 PDT [64978] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 09:06:21.462 PDT [66682] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 09:07:36.303 PDT [66847] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 09:08:03.094 PDT [67041] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 09:09:05.336 PDT [67110] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 09:09:13.806 PDT [67265] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 09:11:00.888 PDT [67474] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 09:14:08.700 PDT [68281] LOG: unexpected EOF on client connection with an open transaction +2021-07-14 09:18:04.828 PDT [68607] LOG: unexpected EOF on client connection with an open transaction From 231d100cc000af4e1f660462cfc4c3d7399d9929 Mon Sep 17 00:00:00 2001 From: peacegypsy Date: Wed, 14 Jul 2021 13:33:14 -0700 Subject: [PATCH 12/19] fixed cards returning on board-id --- app/routes.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/app/routes.py b/app/routes.py index d3234553..727405ef 100644 --- a/app/routes.py +++ b/app/routes.py @@ -60,17 +60,20 @@ def handle_boards(): @boards_bp.route("/", methods=["GET", "PUT", "DELETE"]) def handle_board(board_id): - board = Board.query.get(board_id) - + board = Board.query.get_or_404(board_id) if request.method == "GET": - if board == None: - return make_response("That board does not exist", 404) - return { + cards = [] + for card in board.cards: + single_card = { + "message": card.message, + } + cards.append(single_card) + return make_response({ "id": board.board_id, "title": board.title, "owner": board.owner, - #"cards": board.cards - } + "cards": cards + }) elif request.method == "PUT": if board == None: return make_response("Board does not exist", 404) From a7906a615828aa28f817a25da16a41d343046575 Mon Sep 17 00:00:00 2001 From: nathalia Date: Wed, 14 Jul 2021 15:06:01 -0700 Subject: [PATCH 13/19] Adds route DELETE card inside of a specific Board --- app/routes.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/routes.py b/app/routes.py index 2a4e6867..7722fcd4 100644 --- a/app/routes.py +++ b/app/routes.py @@ -92,7 +92,7 @@ def handle_cards(board_id): "cards": cards_response }, 200) elif request.method == "POST": - request_body = request.get_json() + request_body = request.get_json(force=True) if 'message' not in request_body: return {"details": "Invalid data"}, 400 new_card = Card(message=request_body["message"], @@ -107,3 +107,14 @@ def handle_cards(board_id): "message": new_card.message } }, 201 + + +@boards_bp.route("//", methods=["DELETE"]) +def handle_card(board_id, card_id): + card = Card.query.get_or_404(card_id) + + db.session.delete(card) + db.session.commit() + + return make_response( + f"Card Message: {card.message} Card ID: {card.card_id} deleted successfully") From bf9086f6fc2220b4d93f19509343284f2146bc73 Mon Sep 17 00:00:00 2001 From: nathalia Date: Wed, 14 Jul 2021 15:19:46 -0700 Subject: [PATCH 14/19] git Revert "Adds route DELETE card inside of a specific Board" This reverts commit a7906a615828aa28f817a25da16a41d343046575. --- app/routes.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/app/routes.py b/app/routes.py index b1b2e7f8..727405ef 100644 --- a/app/routes.py +++ b/app/routes.py @@ -115,7 +115,7 @@ def handle_cards(board_id): "cards": cards_response }, 200) elif request.method == "POST": - request_body = request.get_json(force=True) + request_body = request.get_json() if 'message' not in request_body: return {"details": "Invalid data"}, 400 @@ -133,14 +133,3 @@ def handle_cards(board_id): "message": new_card.message } }, 201 - - -@boards_bp.route("//", methods=["DELETE"]) -def handle_card(board_id, card_id): - card = Card.query.get_or_404(card_id) - - db.session.delete(card) - db.session.commit() - - return make_response( - f"Card Message: {card.message} Card ID: {card.card_id} deleted successfully") From 18e3aec2e78bc7d280cb099ed6e59af7ef9b517e Mon Sep 17 00:00:00 2001 From: nathalia Date: Wed, 14 Jul 2021 16:08:13 -0700 Subject: [PATCH 15/19] Adds a DELETE on Card function --- app/routes.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/app/routes.py b/app/routes.py index b1b2e7f8..727405ef 100644 --- a/app/routes.py +++ b/app/routes.py @@ -115,7 +115,7 @@ def handle_cards(board_id): "cards": cards_response }, 200) elif request.method == "POST": - request_body = request.get_json(force=True) + request_body = request.get_json() if 'message' not in request_body: return {"details": "Invalid data"}, 400 @@ -133,14 +133,3 @@ def handle_cards(board_id): "message": new_card.message } }, 201 - - -@boards_bp.route("//", methods=["DELETE"]) -def handle_card(board_id, card_id): - card = Card.query.get_or_404(card_id) - - db.session.delete(card) - db.session.commit() - - return make_response( - f"Card Message: {card.message} Card ID: {card.card_id} deleted successfully") From 213e2c2c636bf562572f84083e96982ccffa3ea8 Mon Sep 17 00:00:00 2001 From: nathalia Date: Wed, 14 Jul 2021 16:28:36 -0700 Subject: [PATCH 16/19] Adds Delete Card --- app/routes.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/routes.py b/app/routes.py index 727405ef..9f6b92a5 100644 --- a/app/routes.py +++ b/app/routes.py @@ -133,3 +133,13 @@ def handle_cards(board_id): "message": new_card.message } }, 201 + +@boards_bp.route("//", methods=["DELETE"]) +def handle_card(board_id, card_id): + card = Card.query.get_or_404(card_id) + + db.session.delete(card) + db.session.commit() + + return make_response( + f"Card Message: {card.message} Card ID: {card.card_id} deleted successfully") From 45a3850ec09a30e112493c2955799969169af45d Mon Sep 17 00:00:00 2001 From: peacegypsy Date: Thu, 15 Jul 2021 10:25:11 -0700 Subject: [PATCH 17/19] adding Nathalias delete card function --- app/routes.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/routes.py b/app/routes.py index 9f6b92a5..9dbe68a8 100644 --- a/app/routes.py +++ b/app/routes.py @@ -14,12 +14,13 @@ load_dotenv() - +#Basic route to test if the server is running @hello_world_bp.route("/hello-world", methods=["GET"]) def hello_world(): my_beautiful_response_body = "Hello, World!" return my_beautiful_response_body +#method to post message to slack def post_message_to_slack(text): SLACK_TOKEN = os.environ.get('SLACKBOT_TOKEN') client = WebClient(token=SLACK_TOKEN) @@ -31,7 +32,7 @@ def post_message_to_slack(text): except SlackApiError as e: assert e.response["error"] - +#routes for getting all boards and creating a new board @boards_bp.route("", methods=["GET", "POST"]) def handle_boards(): if request.method == "GET": @@ -57,7 +58,7 @@ def handle_boards(): return make_response(f"Board {new_board.title} successfully created", 201) - +#routes for getting a specific board, updating a board, and deleting a board @boards_bp.route("/", methods=["GET", "PUT", "DELETE"]) def handle_board(board_id): board = Board.query.get_or_404(board_id) @@ -94,7 +95,7 @@ def handle_board(board_id): return make_response(f"Board: {board.title} sucessfully deleted.") # example_bp = Blueprint('example_bp', __name__) - +#route for getting all cards in a board and making a new card @boards_bp.route("//cards", methods=["POST", "GET"]) def handle_cards(board_id): board = Board.query.get(board_id) @@ -134,6 +135,7 @@ def handle_cards(board_id): } }, 201 +#route for deleting a card @boards_bp.route("//", methods=["DELETE"]) def handle_card(board_id, card_id): card = Card.query.get_or_404(card_id) @@ -143,3 +145,4 @@ def handle_card(board_id, card_id): return make_response( f"Card Message: {card.message} Card ID: {card.card_id} deleted successfully") + From 00941b0ba03552b4be7e2145f5600fb0a5b763a1 Mon Sep 17 00:00:00 2001 From: nathalia Date: Thu, 15 Jul 2021 12:35:32 -0700 Subject: [PATCH 18/19] Add post_message using request --- app/routes.py | 48 +++++++++++++++++++++++++++++------------------- requirements.txt | 1 + 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/app/routes.py b/app/routes.py index 9dbe68a8..a7a4dbda 100644 --- a/app/routes.py +++ b/app/routes.py @@ -5,7 +5,7 @@ import os from dotenv import load_dotenv import requests -from slack_sdk import WebClient +# import slack_sdk from slack_sdk.errors import SlackApiError boards_bp = Blueprint("boards", __name__, url_prefix="/boards") @@ -14,25 +14,30 @@ load_dotenv() -#Basic route to test if the server is running +# Basic route to test if the server is running + + @hello_world_bp.route("/hello-world", methods=["GET"]) def hello_world(): my_beautiful_response_body = "Hello, World!" return my_beautiful_response_body -#method to post message to slack +# method to post message to slack + + def post_message_to_slack(text): SLACK_TOKEN = os.environ.get('SLACKBOT_TOKEN') - client = WebClient(token=SLACK_TOKEN) - try: - response = client.chat_postMessage( - channel='C0286U213J5', - text=text - ) - except SlackApiError as e: - assert e.response["error"] - -#routes for getting all boards and creating a new board + slack_path = "https://slack.com/api/chat.postMessage" + query_params = { + 'channel': 'C0286U213J5', + 'text': text + } + headers = {'Authorization': f"Bearer {SLACK_TOKEN}"} + requests.post(slack_path, params=query_params, headers=headers) + +# routes for getting all boards and creating a new board + + @boards_bp.route("", methods=["GET", "POST"]) def handle_boards(): if request.method == "GET": @@ -58,7 +63,9 @@ def handle_boards(): return make_response(f"Board {new_board.title} successfully created", 201) -#routes for getting a specific board, updating a board, and deleting a board +# routes for getting a specific board, updating a board, and deleting a board + + @boards_bp.route("/", methods=["GET", "PUT", "DELETE"]) def handle_board(board_id): board = Board.query.get_or_404(board_id) @@ -74,7 +81,7 @@ def handle_board(board_id): "title": board.title, "owner": board.owner, "cards": cards - }) + }) elif request.method == "PUT": if board == None: return make_response("Board does not exist", 404) @@ -95,7 +102,9 @@ def handle_board(board_id): return make_response(f"Board: {board.title} sucessfully deleted.") # example_bp = Blueprint('example_bp', __name__) -#route for getting all cards in a board and making a new card +# route for getting all cards in a board and making a new card + + @boards_bp.route("//cards", methods=["POST", "GET"]) def handle_cards(board_id): board = Board.query.get(board_id) @@ -119,7 +128,7 @@ def handle_cards(board_id): request_body = request.get_json() if 'message' not in request_body: return {"details": "Invalid data"}, 400 - + new_card = Card(message=request_body["message"], board_id=board_id) @@ -135,7 +144,9 @@ def handle_cards(board_id): } }, 201 -#route for deleting a card +# route for deleting a card + + @boards_bp.route("//", methods=["DELETE"]) def handle_card(board_id, card_id): card = Card.query.get_or_404(card_id) @@ -145,4 +156,3 @@ def handle_card(board_id, card_id): return make_response( f"Card Message: {card.message} Card ID: {card.card_id} deleted successfully") - diff --git a/requirements.txt b/requirements.txt index 97ca22a7..0eb5bc5b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,6 +27,7 @@ python-dotenv==0.15.0 python-editor==1.0.4 requests==2.25.1 six==1.15.0 +slack-sdk==3.7.0 SQLAlchemy==1.3.23 toml==0.10.2 urllib3==1.26.4 From f328e78e0468a734a0b80de964cb5d849ed836fd Mon Sep 17 00:00:00 2001 From: peacegypsy Date: Fri, 16 Jul 2021 06:42:04 -0700 Subject: [PATCH 19/19] added likes-count to cards --- app/routes.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/routes.py b/app/routes.py index a7a4dbda..a89f4db6 100644 --- a/app/routes.py +++ b/app/routes.py @@ -5,7 +5,6 @@ import os from dotenv import load_dotenv import requests -# import slack_sdk from slack_sdk.errors import SlackApiError boards_bp = Blueprint("boards", __name__, url_prefix="/boards") @@ -117,7 +116,8 @@ def handle_cards(board_id): cards_response = [] for card in cards: cards_response.append({ - "message": card.message + "message": card.message, + "likes_count": card.likes_count, }) return make_response( @@ -140,7 +140,8 @@ def handle_cards(board_id): return { "card": { "id": new_card.card_id, - "message": new_card.message + "message": new_card.message, + "likes_count": new_card.likes_count, } }, 201