Compare commits

..

No commits in common. "f54911ed48baef29d69d283f8f2d28afa1ce97f7" and "75fa82596287126cd4d18c09f40ef1dcaf82e4ba" have entirely different histories.

5 changed files with 40 additions and 141 deletions

View File

@ -14,20 +14,14 @@ __version__ = pkg_resources.get_distribution("flaschengeist_events").version
class EventPlugin(Plugin):
#id = "dev.flaschengeist.events"
#plugin = LocalProxy(lambda: current_app.config["FG_PLUGINS"][EventPlugin.id])
id = "dev.flaschengeist.events"
plugin = LocalProxy(lambda: current_app.config["FG_PLUGINS"][EventPlugin.id])
# provided resources
#permissions = permissions.permissions
permissions = permissions.permissions
blueprint = Blueprint("events", __name__)
models = models
# def __init__(self, cfg):
# super(EventPlugin, self).__init__(cfg)
# 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)
def __init__(self, cfg):
super(EventPlugin, self).__init__(cfg)
from . import routes
from .event_controller import clear_services

View File

@ -1,92 +0,0 @@
"""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 ###

View File

@ -1,7 +1,7 @@
from __future__ import annotations # TODO: Remove if python requirement is >= 3.10
from datetime import datetime
from typing import Optional, Union, List
from typing import Optional, Union
from sqlalchemy import UniqueConstraint
@ -17,7 +17,6 @@ _table_prefix_ = "events_"
class EventType(db.Model, ModelSerializeMixin):
__allow_unmapped__ = True
__tablename__ = _table_prefix_ + "event_type"
id: int = db.Column(Serial, primary_key=True)
name: str = db.Column(db.String(30), nullable=False, unique=True)
@ -35,7 +34,6 @@ class JobType(db.Model, ModelSerializeMixin):
class Service(db.Model, ModelSerializeMixin):
__allow_unmapped__ = True
__tablename__ = _table_prefix_ + "service"
userid: str = ""
is_backup: bool = db.Column(db.Boolean, default=False)
@ -59,7 +57,6 @@ class Service(db.Model, ModelSerializeMixin):
class Job(db.Model, ModelSerializeMixin):
__allow_unmapped__ = True
__tablename__ = _table_prefix_ + "job"
id: int = db.Column(Serial, primary_key=True)
@ -68,7 +65,7 @@ class Job(db.Model, ModelSerializeMixin):
comment: Optional[str] = db.Column(db.String(256))
type: int = db.Column("type_id", Serial, db.ForeignKey(f"{_table_prefix_}job_type.id"), nullable=False)
locked: bool = db.Column(db.Boolean(), default=False, nullable=False)
services: List[Service] = db.relationship(
services: list[Service] = db.relationship(
"Service", back_populates="job_", cascade="save-update, merge, delete, delete-orphan"
)
required_services: float = db.Column(db.Numeric(precision=4, scale=2, asdecimal=False), nullable=False)
@ -88,7 +85,6 @@ class Job(db.Model, ModelSerializeMixin):
class Event(db.Model, ModelSerializeMixin):
"""Model for an Event"""
__allow_unmapped__ = True
__tablename__ = _table_prefix_ + "event"
id: int = db.Column(Serial, primary_key=True)
start: datetime = db.Column(UtcDateTime, nullable=False)
@ -97,7 +93,7 @@ class Event(db.Model, ModelSerializeMixin):
description: Optional[str] = db.Column(db.String(512))
type: Union[EventType, int] = db.relationship("EventType")
is_template: bool = db.Column(db.Boolean, default=False)
jobs: List[Job] = db.relationship(
jobs: list[Job] = db.relationship(
"Job",
back_populates="event_",
cascade="all,delete,delete-orphan",
@ -113,7 +109,6 @@ class Event(db.Model, ModelSerializeMixin):
class Invitation(db.Model, ModelSerializeMixin):
__allow_unmapped__ = True
__tablename__ = _table_prefix_ + "invitation"
id: int = db.Column(Serial, primary_key=True)

View File

@ -1,5 +1,5 @@
from http.client import NO_CONTENT
from flask import request, jsonify, Blueprint
from flask import request, jsonify
from werkzeug.exceptions import BadRequest, NotFound, Forbidden
from flaschengeist.models.session import Session
@ -11,8 +11,6 @@ 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:
@ -27,14 +25,14 @@ def dict_get(self, key, default=None, type=None):
return rv
@blueprint.route("/events/templates", methods=["GET"])
@EventPlugin.blueprint.route("/events/templates", methods=["GET"])
@login_required()
def get_templates(current_session):
return jsonify(event_controller.get_templates())
@blueprint.route("/events/event-types", methods=["GET"])
@blueprint.route("/events/event-types/<int:identifier>", methods=["GET"])
@EventPlugin.blueprint.route("/events/event-types", methods=["GET"])
@EventPlugin.blueprint.route("/events/event-types/<int:identifier>", methods=["GET"])
@login_required()
def get_event_types(current_session, identifier=None):
"""Get EventType(s)
@ -56,7 +54,7 @@ def get_event_types(current_session, identifier=None):
return jsonify(result)
@blueprint.route("/events/event-types", methods=["POST"])
@EventPlugin.blueprint.route("/events/event-types", methods=["POST"])
@login_required(permission=permissions.EVENT_TYPE)
def new_event_type(current_session):
"""Create a new EventType
@ -78,7 +76,7 @@ def new_event_type(current_session):
return jsonify(event_type)
@blueprint.route("/events/event-types/<int:identifier>", methods=["PUT", "DELETE"])
@EventPlugin.blueprint.route("/events/event-types/<int:identifier>", methods=["PUT", "DELETE"])
@login_required(permission=permissions.EVENT_TYPE)
def modify_event_type(identifier, current_session):
"""Rename or delete an event type
@ -104,7 +102,7 @@ def modify_event_type(identifier, current_session):
return "", NO_CONTENT
@blueprint.route("/events/job-types", methods=["GET"])
@EventPlugin.blueprint.route("/events/job-types", methods=["GET"])
@login_required()
def get_job_types(current_session):
"""Get all JobTypes
@ -121,7 +119,7 @@ def get_job_types(current_session):
return jsonify(types)
@blueprint.route("/events/job-types", methods=["POST"])
@EventPlugin.blueprint.route("/events/job-types", methods=["POST"])
@login_required(permission=permissions.JOB_TYPE)
def new_job_type(current_session):
"""Create a new JobType
@ -143,7 +141,7 @@ def new_job_type(current_session):
return jsonify(jt)
@blueprint.route("/events/job-types/<int:type_id>", methods=["PUT", "DELETE"])
@EventPlugin.blueprint.route("/events/job-types/<int:type_id>", methods=["PUT", "DELETE"])
@login_required(permission=permissions.JOB_TYPE)
def modify_job_type(type_id, current_session):
"""Rename or delete a JobType
@ -169,7 +167,7 @@ def modify_job_type(type_id, current_session):
return "", NO_CONTENT
@blueprint.route("/events/<int:event_id>", methods=["GET"])
@EventPlugin.blueprint.route("/events/<int:event_id>", methods=["GET"])
@login_required()
def get_event(event_id, current_session):
"""Get event by id
@ -190,7 +188,7 @@ def get_event(event_id, current_session):
return jsonify(event)
@blueprint.route("/events", methods=["GET"])
@EventPlugin.blueprint.route("/events", methods=["GET"])
@login_required()
def get_events(current_session):
count, result = event_controller.get_events(
@ -220,7 +218,7 @@ def _add_job(event, data):
)
@blueprint.route("/events", methods=["POST"])
@EventPlugin.blueprint.route("/events", methods=["POST"])
@login_required(permission=permissions.CREATE)
def create_event(current_session):
"""Create an new event
@ -261,7 +259,7 @@ def create_event(current_session):
raise BadRequest("Invalid parameter")
@blueprint.route("/events/<int:event_id>", methods=["PUT"])
@EventPlugin.blueprint.route("/events/<int:event_id>", methods=["PUT"])
@login_required(permission=permissions.EDIT)
def modify_event(event_id, current_session):
"""Modify an event
@ -291,7 +289,7 @@ def modify_event(event_id, current_session):
return jsonify(event)
@blueprint.route("/events/<int:event_id>", methods=["DELETE"])
@EventPlugin.blueprint.route("/events/<int:event_id>", methods=["DELETE"])
@login_required(permission=permissions.DELETE)
def delete_event(event_id, current_session):
"""Delete an event
@ -309,7 +307,7 @@ def delete_event(event_id, current_session):
return "", NO_CONTENT
@blueprint.route("/events/<int:event_id>/jobs", methods=["POST"])
@EventPlugin.blueprint.route("/events/<int:event_id>/jobs", methods=["POST"])
@login_required(permission=permissions.EDIT)
def add_job(event_id, current_session):
"""Add an new Job to an Event / EventSlot
@ -330,7 +328,7 @@ def add_job(event_id, current_session):
return jsonify(event)
@blueprint.route("/events/<int:event_id>/jobs/<int:job_id>", methods=["DELETE"])
@EventPlugin.blueprint.route("/events/<int:event_id>/jobs/<int:job_id>", methods=["DELETE"])
@login_required(permission=permissions.DELETE)
def delete_job(event_id, job_id, current_session):
"""Delete a Job
@ -350,7 +348,7 @@ def delete_job(event_id, job_id, current_session):
return no_content()
@blueprint.route("/events/<int:event_id>/jobs/<int:job_id>", methods=["PUT"])
@EventPlugin.blueprint.route("/events/<int:event_id>/jobs/<int:job_id>", methods=["PUT"])
@login_required()
def update_job(event_id, job_id, current_session: Session):
"""Edit Job
@ -392,20 +390,20 @@ def update_job(event_id, job_id, current_session: Session):
return jsonify(job)
@blueprint.route("/events/jobs", methods=["GET"])
@EventPlugin.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})
@blueprint.route("/events/jobs/<int:job_id>", methods=["GET"])
@EventPlugin.blueprint.route("/events/jobs/<int:job_id>", methods=["GET"])
@login_required()
def get_job(job_id, current_session: Session):
return jsonify(event_controller.get_job(job_id))
@blueprint.route("/events/jobs/<int:job_id>/assign", methods=["POST"])
@EventPlugin.blueprint.route("/events/jobs/<int:job_id>/assign", methods=["POST"])
@login_required()
def assign_job(job_id, current_session: Session):
"""Assign / unassign user to the Job
@ -441,7 +439,7 @@ def assign_job(job_id, current_session: Session):
return jsonify(job)
@blueprint.route("/events/jobs/<int:job_id>/lock", methods=["POST"])
@EventPlugin.blueprint.route("/events/jobs/<int:job_id>/lock", methods=["POST"])
@login_required(permissions.LOCK_JOBS)
def lock_job(job_id, current_session: Session):
"""Lock / unlock the Job
@ -468,7 +466,7 @@ def lock_job(job_id, current_session: Session):
return no_content()
@blueprint.route("/events/invitations", methods=["POST"])
@EventPlugin.blueprint.route("/events/invitations", methods=["POST"])
@login_required()
def invite(current_session: Session):
"""Invite an user to a job or transfer job
@ -506,13 +504,13 @@ def invite(current_session: Session):
raise BadRequest
@blueprint.route("/events/invitations", methods=["GET"])
@EventPlugin.blueprint.route("/events/invitations", methods=["GET"])
@login_required()
def get_invitations(current_session: Session):
return jsonify(event_controller.get_invitations(current_session.user_))
@blueprint.route("/events/invitations/<int:invitation_id>", methods=["GET"])
@EventPlugin.blueprint.route("/events/invitations/<int:invitation_id>", methods=["GET"])
@login_required()
def get_invitation(invitation_id: int, current_session: Session):
inv = event_controller.get_invitation(invitation_id)
@ -521,7 +519,7 @@ def get_invitation(invitation_id: int, current_session: Session):
return jsonify(inv)
@blueprint.route("/events/invitations/<int:invitation_id>", methods=["DELETE", "PUT"])
@EventPlugin.blueprint.route("/events/invitations/<int:invitation_id>", methods=["DELETE", "PUT"])
@login_required()
def respond_invitation(invitation_id: int, current_session: Session):
inv = event_controller.get_invitation(invitation_id)

View File

@ -28,6 +28,8 @@
</q-card>
</q-dialog>
<q-card>
<q-card-section>
<q-table :title="title" :rows="rows" row-key="id" :columns="columns">
<template #top-right>
<q-input
@ -49,6 +51,8 @@
</q-td>
</template>
</q-table>
</q-card-section>
</q-card>
</div>
</template>