diff --git a/backend/flaschengeist_events/__init__.py b/backend/flaschengeist_events/__init__.py index 9cf458e..f6fbd0b 100644 --- a/backend/flaschengeist_events/__init__.py +++ b/backend/flaschengeist_events/__init__.py @@ -18,7 +18,6 @@ class EventPlugin(Plugin): #plugin = LocalProxy(lambda: current_app.config["FG_PLUGINS"][EventPlugin.id]) # provided resources #permissions = permissions.permissions - blueprint = Blueprint("events", __name__) models = models # def __init__(self, cfg): @@ -26,5 +25,9 @@ class EventPlugin(Plugin): # from . import routes # from .event_controller import clear_services + def load(self): + from .routes import blueprint + self.blueprint = blueprint + def install(self): self.install_permissions(permissions.permissions) diff --git a/backend/flaschengeist_events/migrations/e70508bd8cb4_init_events.py b/backend/flaschengeist_events/migrations/e70508bd8cb4_init_events.py new file mode 100644 index 0000000..08303e9 --- /dev/null +++ b/backend/flaschengeist_events/migrations/e70508bd8cb4_init_events.py @@ -0,0 +1,92 @@ +"""init events + +Revision ID: e70508bd8cb4 +Revises: 20482a003db8 +Create Date: 2023-04-10 14:21:47.007251 + +""" +from alembic import op +import sqlalchemy as sa +import flaschengeist + + +# revision identifiers, used by Alembic. +revision = 'e70508bd8cb4' +down_revision = None +branch_labels = ('events',) +depends_on = "flaschengeist" + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('events_event_type', + sa.Column('id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('name', sa.String(length=30), nullable=False), + sa.PrimaryKeyConstraint('id', name=op.f('pk_events_event_type')), + sa.UniqueConstraint('name', name=op.f('uq_events_event_type_name')) + ) + op.create_table('events_job_type', + sa.Column('id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('name', sa.String(length=30), nullable=False), + sa.PrimaryKeyConstraint('id', name=op.f('pk_events_job_type')), + sa.UniqueConstraint('name', name=op.f('uq_events_job_type_name')) + ) + op.create_table('events_event', + sa.Column('id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('start', flaschengeist.database.types.UtcDateTime(), nullable=False), + sa.Column('end', flaschengeist.database.types.UtcDateTime(), nullable=True), + sa.Column('name', sa.String(length=255), nullable=True), + sa.Column('description', sa.String(length=512), nullable=True), + sa.Column('is_template', sa.Boolean(), nullable=True), + sa.Column('type_id', flaschengeist.database.types.Serial(), nullable=False), + sa.ForeignKeyConstraint(['type_id'], ['events_event_type.id'], name=op.f('fk_events_event_type_id_events_event_type'), ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id', name=op.f('pk_events_event')) + ) + op.create_table('events_job', + sa.Column('id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('start', flaschengeist.database.types.UtcDateTime(), nullable=False), + sa.Column('end', flaschengeist.database.types.UtcDateTime(), nullable=True), + sa.Column('comment', sa.String(length=256), nullable=True), + sa.Column('type_id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('locked', sa.Boolean(), nullable=False), + sa.Column('required_services', sa.Numeric(precision=4, scale=2, asdecimal=False), nullable=False), + sa.Column('event_id', flaschengeist.database.types.Serial(), nullable=False), + sa.ForeignKeyConstraint(['event_id'], ['events_event.id'], name=op.f('fk_events_job_event_id_events_event')), + sa.ForeignKeyConstraint(['type_id'], ['events_job_type.id'], name=op.f('fk_events_job_type_id_events_job_type')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_events_job')), + sa.UniqueConstraint('type_id', 'start', 'event_id', name='_type_start_uc') + ) + op.create_table('events_invitation', + sa.Column('id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('time', flaschengeist.database.types.UtcDateTime(), nullable=False), + sa.Column('job_id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('invitee_id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('inviter_id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('transferee_id', flaschengeist.database.types.Serial(), nullable=True), + sa.ForeignKeyConstraint(['invitee_id'], ['user.id'], name=op.f('fk_events_invitation_invitee_id_user')), + sa.ForeignKeyConstraint(['inviter_id'], ['user.id'], name=op.f('fk_events_invitation_inviter_id_user')), + sa.ForeignKeyConstraint(['job_id'], ['events_job.id'], name=op.f('fk_events_invitation_job_id_events_job')), + sa.ForeignKeyConstraint(['transferee_id'], ['user.id'], name=op.f('fk_events_invitation_transferee_id_user')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_events_invitation')) + ) + op.create_table('events_service', + sa.Column('is_backup', sa.Boolean(), nullable=True), + sa.Column('value', sa.Numeric(precision=3, scale=2, asdecimal=False), nullable=False), + sa.Column('job_id', flaschengeist.database.types.Serial(), nullable=False), + sa.Column('user_id', flaschengeist.database.types.Serial(), nullable=False), + sa.ForeignKeyConstraint(['job_id'], ['events_job.id'], name=op.f('fk_events_service_job_id_events_job')), + sa.ForeignKeyConstraint(['user_id'], ['user.id'], name=op.f('fk_events_service_user_id_user')), + sa.PrimaryKeyConstraint('job_id', 'user_id', name=op.f('pk_events_service')) + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('events_service') + op.drop_table('events_invitation') + op.drop_table('events_job') + op.drop_table('events_event') + op.drop_table('events_job_type') + op.drop_table('events_event_type') + # ### end Alembic commands ### diff --git a/backend/flaschengeist_events/routes.py b/backend/flaschengeist_events/routes.py index 18d184e..4508049 100644 --- a/backend/flaschengeist_events/routes.py +++ b/backend/flaschengeist_events/routes.py @@ -1,5 +1,5 @@ from http.client import NO_CONTENT -from flask import request, jsonify +from flask import request, jsonify, Blueprint from werkzeug.exceptions import BadRequest, NotFound, Forbidden from flaschengeist.models.session import Session @@ -11,6 +11,8 @@ from flaschengeist.utils.HTTP import get_filter_args, no_content from . import event_controller, permissions, EventPlugin +blueprint = Blueprint("events", __name__) + def dict_get(self, key, default=None, type=None): """Same as .get from MultiDict""" try: @@ -25,14 +27,14 @@ def dict_get(self, key, default=None, type=None): return rv -@EventPlugin.blueprint.route("/events/templates", methods=["GET"]) +@blueprint.route("/events/templates", methods=["GET"]) @login_required() def get_templates(current_session): return jsonify(event_controller.get_templates()) -@EventPlugin.blueprint.route("/events/event-types", methods=["GET"]) -@EventPlugin.blueprint.route("/events/event-types/", methods=["GET"]) +@blueprint.route("/events/event-types", methods=["GET"]) +@blueprint.route("/events/event-types/", methods=["GET"]) @login_required() def get_event_types(current_session, identifier=None): """Get EventType(s) @@ -54,7 +56,7 @@ def get_event_types(current_session, identifier=None): return jsonify(result) -@EventPlugin.blueprint.route("/events/event-types", methods=["POST"]) +@blueprint.route("/events/event-types", methods=["POST"]) @login_required(permission=permissions.EVENT_TYPE) def new_event_type(current_session): """Create a new EventType @@ -76,7 +78,7 @@ def new_event_type(current_session): return jsonify(event_type) -@EventPlugin.blueprint.route("/events/event-types/", methods=["PUT", "DELETE"]) +@blueprint.route("/events/event-types/", methods=["PUT", "DELETE"]) @login_required(permission=permissions.EVENT_TYPE) def modify_event_type(identifier, current_session): """Rename or delete an event type @@ -102,7 +104,7 @@ def modify_event_type(identifier, current_session): return "", NO_CONTENT -@EventPlugin.blueprint.route("/events/job-types", methods=["GET"]) +@blueprint.route("/events/job-types", methods=["GET"]) @login_required() def get_job_types(current_session): """Get all JobTypes @@ -119,7 +121,7 @@ def get_job_types(current_session): return jsonify(types) -@EventPlugin.blueprint.route("/events/job-types", methods=["POST"]) +@blueprint.route("/events/job-types", methods=["POST"]) @login_required(permission=permissions.JOB_TYPE) def new_job_type(current_session): """Create a new JobType @@ -141,7 +143,7 @@ def new_job_type(current_session): return jsonify(jt) -@EventPlugin.blueprint.route("/events/job-types/", methods=["PUT", "DELETE"]) +@blueprint.route("/events/job-types/", methods=["PUT", "DELETE"]) @login_required(permission=permissions.JOB_TYPE) def modify_job_type(type_id, current_session): """Rename or delete a JobType @@ -167,7 +169,7 @@ def modify_job_type(type_id, current_session): return "", NO_CONTENT -@EventPlugin.blueprint.route("/events/", methods=["GET"]) +@blueprint.route("/events/", methods=["GET"]) @login_required() def get_event(event_id, current_session): """Get event by id @@ -188,7 +190,7 @@ def get_event(event_id, current_session): return jsonify(event) -@EventPlugin.blueprint.route("/events", methods=["GET"]) +@blueprint.route("/events", methods=["GET"]) @login_required() def get_events(current_session): count, result = event_controller.get_events( @@ -218,7 +220,7 @@ def _add_job(event, data): ) -@EventPlugin.blueprint.route("/events", methods=["POST"]) +@blueprint.route("/events", methods=["POST"]) @login_required(permission=permissions.CREATE) def create_event(current_session): """Create an new event @@ -259,7 +261,7 @@ def create_event(current_session): raise BadRequest("Invalid parameter") -@EventPlugin.blueprint.route("/events/", methods=["PUT"]) +@blueprint.route("/events/", methods=["PUT"]) @login_required(permission=permissions.EDIT) def modify_event(event_id, current_session): """Modify an event @@ -289,7 +291,7 @@ def modify_event(event_id, current_session): return jsonify(event) -@EventPlugin.blueprint.route("/events/", methods=["DELETE"]) +@blueprint.route("/events/", methods=["DELETE"]) @login_required(permission=permissions.DELETE) def delete_event(event_id, current_session): """Delete an event @@ -307,7 +309,7 @@ def delete_event(event_id, current_session): return "", NO_CONTENT -@EventPlugin.blueprint.route("/events//jobs", methods=["POST"]) +@blueprint.route("/events//jobs", methods=["POST"]) @login_required(permission=permissions.EDIT) def add_job(event_id, current_session): """Add an new Job to an Event / EventSlot @@ -328,7 +330,7 @@ def add_job(event_id, current_session): return jsonify(event) -@EventPlugin.blueprint.route("/events//jobs/", methods=["DELETE"]) +@blueprint.route("/events//jobs/", methods=["DELETE"]) @login_required(permission=permissions.DELETE) def delete_job(event_id, job_id, current_session): """Delete a Job @@ -348,7 +350,7 @@ def delete_job(event_id, job_id, current_session): return no_content() -@EventPlugin.blueprint.route("/events//jobs/", methods=["PUT"]) +@blueprint.route("/events//jobs/", methods=["PUT"]) @login_required() def update_job(event_id, job_id, current_session: Session): """Edit Job @@ -390,20 +392,20 @@ def update_job(event_id, job_id, current_session: Session): return jsonify(job) -@EventPlugin.blueprint.route("/events/jobs", methods=["GET"]) +@blueprint.route("/events/jobs", methods=["GET"]) @login_required() def get_jobs(current_session: Session): count, result = event_controller.get_jobs(current_session.user_, *get_filter_args()) return jsonify({"count": count, "result": result}) -@EventPlugin.blueprint.route("/events/jobs/", methods=["GET"]) +@blueprint.route("/events/jobs/", methods=["GET"]) @login_required() def get_job(job_id, current_session: Session): return jsonify(event_controller.get_job(job_id)) -@EventPlugin.blueprint.route("/events/jobs//assign", methods=["POST"]) +@blueprint.route("/events/jobs//assign", methods=["POST"]) @login_required() def assign_job(job_id, current_session: Session): """Assign / unassign user to the Job @@ -439,7 +441,7 @@ def assign_job(job_id, current_session: Session): return jsonify(job) -@EventPlugin.blueprint.route("/events/jobs//lock", methods=["POST"]) +@blueprint.route("/events/jobs//lock", methods=["POST"]) @login_required(permissions.LOCK_JOBS) def lock_job(job_id, current_session: Session): """Lock / unlock the Job @@ -466,7 +468,7 @@ def lock_job(job_id, current_session: Session): return no_content() -@EventPlugin.blueprint.route("/events/invitations", methods=["POST"]) +@blueprint.route("/events/invitations", methods=["POST"]) @login_required() def invite(current_session: Session): """Invite an user to a job or transfer job @@ -504,13 +506,13 @@ def invite(current_session: Session): raise BadRequest -@EventPlugin.blueprint.route("/events/invitations", methods=["GET"]) +@blueprint.route("/events/invitations", methods=["GET"]) @login_required() def get_invitations(current_session: Session): return jsonify(event_controller.get_invitations(current_session.user_)) -@EventPlugin.blueprint.route("/events/invitations/", methods=["GET"]) +@blueprint.route("/events/invitations/", methods=["GET"]) @login_required() def get_invitation(invitation_id: int, current_session: Session): inv = event_controller.get_invitation(invitation_id) @@ -519,7 +521,7 @@ def get_invitation(invitation_id: int, current_session: Session): return jsonify(inv) -@EventPlugin.blueprint.route("/events/invitations/", methods=["DELETE", "PUT"]) +@blueprint.route("/events/invitations/", methods=["DELETE", "PUT"]) @login_required() def respond_invitation(invitation_id: int, current_session: Session): inv = event_controller.get_invitation(invitation_id) diff --git a/src/components/management/ManageTypes.vue b/src/components/management/ManageTypes.vue index 2cd2ef1..c076369 100644 --- a/src/components/management/ManageTypes.vue +++ b/src/components/management/ManageTypes.vue @@ -28,8 +28,6 @@ - - - -