Ukladani metadat k planum
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
"""add flight plan meta information
|
||||
|
||||
Revision ID: 790ba00fc021
|
||||
Revises: f7ab4bdac987
|
||||
Create Date: 2024-04-29 16:40:09.829317
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '790ba00fc021'
|
||||
down_revision = 'f7ab4bdac987'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('flight_plan_has_copilot',
|
||||
sa.Column('flight_plan_id', sa.Integer(), nullable=False),
|
||||
sa.Column('copilot_id', sa.Integer(), nullable=False),
|
||||
sa.Column('token', sa.String(length=64), nullable=True),
|
||||
sa.ForeignKeyConstraint(['copilot_id'], ['copilot.id'], ),
|
||||
sa.ForeignKeyConstraint(['flight_plan_id'], ['flight_plan.id'], ),
|
||||
sa.PrimaryKeyConstraint('flight_plan_id', 'copilot_id'),
|
||||
sa.UniqueConstraint('token')
|
||||
)
|
||||
op.add_column('flight_plan', sa.Column('is_default_name', sa.Boolean(), server_default='0', nullable=False))
|
||||
op.add_column('flight_plan', sa.Column('is_editable_by_copilot', sa.Boolean(), server_default='0', nullable=False))
|
||||
op.add_column('flight_plan', sa.Column('planned_speed', sa.Integer(), nullable=False))
|
||||
op.add_column('flight_plan', sa.Column('planned_takeoff_datetime', sa.DateTime(), nullable=True))
|
||||
op.add_column('flight_plan', sa.Column('aircraft_id', sa.Integer(), nullable=True))
|
||||
op.alter_column('flight_plan', 'name',
|
||||
existing_type=mysql.VARCHAR(length=128),
|
||||
type_=sa.String(length=256),
|
||||
existing_nullable=False)
|
||||
op.create_foreign_key(None, 'flight_plan', 'aircraft', ['aircraft_id'], ['id'])
|
||||
op.drop_column('point_of_interest_type', 'openaip_id')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('point_of_interest_type', sa.Column('openaip_id', mysql.VARCHAR(length=32), nullable=False))
|
||||
op.drop_constraint(None, 'flight_plan', type_='foreignkey')
|
||||
op.alter_column('flight_plan', 'name',
|
||||
existing_type=sa.String(length=256),
|
||||
type_=mysql.VARCHAR(length=128),
|
||||
existing_nullable=False)
|
||||
op.drop_column('flight_plan', 'aircraft_id')
|
||||
op.drop_column('flight_plan', 'planned_takeoff_datetime')
|
||||
op.drop_column('flight_plan', 'planned_speed')
|
||||
op.drop_column('flight_plan', 'is_editable_by_copilot')
|
||||
op.drop_column('flight_plan', 'is_default_name')
|
||||
op.drop_table('flight_plan_has_copilot')
|
||||
# ### end Alembic commands ###
|
||||
+18
-1
@@ -59,6 +59,14 @@ flight_has_copilot = Table(
|
||||
Column("token", String(64), unique=True)
|
||||
)
|
||||
|
||||
flight_plan_has_copilot = Table(
|
||||
"flight_plan_has_copilot",
|
||||
BaseModel.metadata,
|
||||
Column("flight_plan_id", ForeignKey("flight_plan.id"), primary_key=True),
|
||||
Column("copilot_id", ForeignKey("copilot.id"), primary_key=True),
|
||||
Column("token", String(64), unique=True)
|
||||
)
|
||||
|
||||
copilot_has_photo = Table(
|
||||
"copilot_has_photo",
|
||||
BaseModel.metadata,
|
||||
@@ -93,12 +101,20 @@ class FlightPlan(BaseModel):
|
||||
__tablename__ = "flight_plan"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
name: Mapped[str] = mapped_column(String(128), nullable=False)
|
||||
name: Mapped[str] = mapped_column(String(256), nullable=False)
|
||||
is_default_name: Mapped[bool] = mapped_column(Boolean, server_default='0')
|
||||
is_public: Mapped[bool] = mapped_column(Boolean, server_default='0')
|
||||
is_editable_by_copilot: Mapped[bool] = mapped_column(Boolean, server_default='0')
|
||||
planned_speed: Mapped[int] = mapped_column(Integer, nullable=False, default=150)
|
||||
planned_takeoff_datetime: Mapped[datetime] = mapped_column(DateTime, nullable=True)
|
||||
aircraft_id: Mapped[int] = mapped_column(Integer, ForeignKey("aircraft.id"), nullable=True)
|
||||
created_by_id: Mapped[int] = mapped_column(Integer, ForeignKey('user.id'))
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
|
||||
deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default='0')
|
||||
|
||||
copilots: Mapped[List['Copilot']] = relationship(secondary=flight_plan_has_copilot)
|
||||
aircraft: Mapped['Aircraft'] = relationship()
|
||||
markers: Mapped['FlightPlanMarker'] = relationship()
|
||||
created_by: Mapped['User'] = relationship()
|
||||
|
||||
|
||||
@@ -403,6 +419,7 @@ class Copilot(BaseModel):
|
||||
deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, server_default='0')
|
||||
|
||||
flights: Mapped[Set['Flight']] = relationship(secondary=flight_has_copilot)
|
||||
flight_plans: Mapped[Set['FlightPlan']] = relationship(secondary=flight_plan_has_copilot)
|
||||
created_by: Mapped['User'] = relationship()
|
||||
photos: Mapped[List['Photo']] = relationship(secondary=copilot_has_photo)
|
||||
title_photo: Mapped['Photo'] = relationship(foreign_keys=[title_photo_id])
|
||||
|
||||
@@ -20,9 +20,25 @@ flight_copilots_dataloader = DataLoader(
|
||||
models.flight_has_copilot.c.flight_id == models.Flight.id,
|
||||
models.flight_has_copilot.c.copilot_id == models.Copilot.id,
|
||||
],
|
||||
extra_join=[models.Copilot.flights]).load,
|
||||
extra_join=[models.Copilot.flights]
|
||||
).load,
|
||||
cache=False)
|
||||
|
||||
|
||||
flight_plan_copilots_dataloader = DataLoader(
|
||||
load_fn=FlightCopilotDataloader(
|
||||
models.Copilot,
|
||||
relationship_column=models.FlightPlan.id,
|
||||
extra_select=[models.flight_plan_has_copilot.c.token],
|
||||
# filters=[
|
||||
# models.flight_plan_has_copilot.c.flight_plan_id == models.FlightPlan.id,
|
||||
# models.flight_plan_has_copilot.c.copilot_id == models.Copilot.id,
|
||||
# ],
|
||||
extra_join=[models.Copilot.flight_plans]
|
||||
).load,
|
||||
cache=False
|
||||
)
|
||||
|
||||
reporting_points_dataloader = DataLoader(
|
||||
load_fn=MultiModelsDataloader(
|
||||
models.ReportingPoint,
|
||||
|
||||
@@ -87,7 +87,7 @@ class BaseQueryResolver(BaseResolver):
|
||||
|
||||
|
||||
class BaseMutationResolver(BaseResolver):
|
||||
async def _get_one(self, db: AsyncSession, id: int, created_by_id: int) -> models.BaseModel:
|
||||
async def _get_one(self, db: AsyncSession, id: int, created_by_id: int):
|
||||
query = self.query_builder.get_simple_query(created_by_id=created_by_id).filter(self.model.id == id)
|
||||
return (await db.scalars(query)).one()
|
||||
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
from sqlalchemy import delete
|
||||
import asyncio
|
||||
|
||||
from sqlalchemy import delete, select
|
||||
from sqlalchemy.dialects.mysql import insert
|
||||
|
||||
from database import models
|
||||
from database.models import flight_plan_has_copilot
|
||||
from database.transaction import get_session
|
||||
from graphql_schema.entities.helpers.combobox import handle_combobox_save
|
||||
from graphql_schema.entities.resolvers.base import BaseMutationResolver
|
||||
from graphql_schema.entities.resolvers.flight import handle_aircraft_save
|
||||
from graphql_schema.entities.types.mutation_input import CreateFlightPlanInput, EditFlightPlanInput
|
||||
from graphql_schema.entities.types.types import FlightPlan
|
||||
from utils.str_utils import random_str
|
||||
|
||||
|
||||
class FlightPlanMutationResolver(BaseMutationResolver):
|
||||
@@ -41,13 +49,55 @@ class FlightPlanMutationResolver(BaseMutationResolver):
|
||||
await self.save_markers(db, flight_plan, data.markers)
|
||||
return flight_plan
|
||||
|
||||
async def save_copilots(self, db, flight_plan_id: int, copilots: list, user_id: int):
|
||||
await db.execute(delete(flight_plan_has_copilot).filter_by(flight_plan_id=flight_plan_id))
|
||||
copilots = await asyncio.gather(*[
|
||||
handle_combobox_save(db, models.Copilot, copilot, user_id) for copilot in copilots
|
||||
])
|
||||
|
||||
for copilot_id in copilots:
|
||||
await db.execute(insert(flight_plan_has_copilot).values(
|
||||
flight_plan_id=flight_plan_id,
|
||||
copilot_id=copilot_id,
|
||||
token=random_str(64)
|
||||
))
|
||||
|
||||
async def update(self, id: int, data: EditFlightPlanInput, user_id: int) -> FlightPlan:
|
||||
input_data = data.to_dict()
|
||||
|
||||
async with get_session() as db:
|
||||
flight_plan = await self._do_update(db, id, input_data)
|
||||
flight_plan_model = await self._get_one(db, id=id, created_by_id=user_id)
|
||||
|
||||
await self.reset_plan_markers(db, flight_plan)
|
||||
await self.save_markers(db, flight_plan, data.markers)
|
||||
if data.aircraft is not None:
|
||||
input_data['aircraft_id'] = await handle_aircraft_save(db, user_id, data.aircraft)
|
||||
|
||||
if data.markers is not None:
|
||||
await self.reset_plan_markers(db, flight_plan_model)
|
||||
await self.save_markers(db, flight_plan_model, data.markers)
|
||||
|
||||
if flight_plan_model.is_default_name:
|
||||
if data.markers:
|
||||
markers = data.markers
|
||||
else:
|
||||
markers = (await db.scalars(select(models.FlightPlanMarker).filter(models.FlightPlanMarker.flight_plan_id == id))).all()
|
||||
|
||||
used_markers = evenly_spaced_elements(markers, 5)
|
||||
input_data['name'] = " - ".join(m.name for m in used_markers)
|
||||
|
||||
if data.copilots is not None:
|
||||
await self.save_copilots(
|
||||
db,
|
||||
flight_plan_id=id,
|
||||
copilots=data.copilots,
|
||||
user_id=user_id
|
||||
)
|
||||
|
||||
flight_plan = await self._do_update(db, obj=flight_plan_model, data=input_data)
|
||||
return flight_plan
|
||||
|
||||
|
||||
def evenly_spaced_elements(lst: list, count: int) -> list:
|
||||
if count > len(lst):
|
||||
return lst
|
||||
interval = (len(lst) - 1) / (count - 1) if count > 1 else 0
|
||||
return [lst[int(round(i * interval))] for i in range(count)]
|
||||
|
||||
@@ -5,6 +5,7 @@ import strawberry
|
||||
from strawberry.file_uploads import Upload
|
||||
from database import models
|
||||
from graphql_schema.entities.types.base import BaseGraphqlInputType
|
||||
from graphql_schema.entities.types.types import Aircraft
|
||||
from graphql_schema.sqlalchemy_to_strawberry_type import strawberry_sqlalchemy_input
|
||||
|
||||
|
||||
@@ -36,7 +37,9 @@ class CreateFlightPlanInput(BaseGraphqlInputType):
|
||||
|
||||
@strawberry_sqlalchemy_input(model=models.FlightPlan, exclude_fields=["id", "markers"], all_optional=True)
|
||||
class EditFlightPlanInput(BaseGraphqlInputType):
|
||||
markers: list[FlightPlanMarkerInput]
|
||||
markers: Optional[list[FlightPlanMarkerInput]] = None
|
||||
copilots: Optional[list[ComboboxInput]] = None
|
||||
aircraft: Optional[ComboboxInput] = None
|
||||
|
||||
|
||||
@strawberry_sqlalchemy_input(model=models.Copilot, exclude_fields=["id"], all_optional=True)
|
||||
|
||||
@@ -14,7 +14,8 @@ from graphql_schema.dataloaders.multi_models import (
|
||||
photos_dataloader, flights_by_aircraft_dataloader, users_in_organization_dataloader,
|
||||
aircrafts_from_organization_dataloader, user_organizations_dataloader, flights_by_event_dataloader,
|
||||
flights_by_copilot_dataloader, public_flights_by_event_dataloader, public_flights_by_copilot_dataloader,
|
||||
photo_copilots_dataloader, photos_aircraft_dataloader, copilots_in_photo_dataloader, flight_plan_markers_dataloader, reporting_points_dataloader
|
||||
photo_copilots_dataloader, photos_aircraft_dataloader, copilots_in_photo_dataloader, flight_plan_markers_dataloader,
|
||||
reporting_points_dataloader, flight_plan_copilots_dataloader
|
||||
)
|
||||
from graphql_schema.dataloaders.single_model import (
|
||||
poi_dataloader, poi_type_dataloader, event_dataloader, aircraft_dataloader, airport_dataloader,
|
||||
@@ -227,12 +228,18 @@ class FlightPlan:
|
||||
)
|
||||
return navigation
|
||||
|
||||
@authenticated_user_only(raise_when_unauthorized=False, return_value_unauthorized=[])
|
||||
async def load_copilots(root):
|
||||
return await flight_plan_copilots_dataloader.load(root.id)
|
||||
|
||||
markers: list[FlightPlanMarker] = strawberry.field(
|
||||
resolver=lambda root: flight_plan_markers_dataloader.load(root.id)
|
||||
)
|
||||
track: Optional[list[FlightPlanTrack]] = strawberry.field(
|
||||
resolver=resolve_track
|
||||
)
|
||||
copilots: List[Copilot] = strawberry.field(resolver=load_copilots)
|
||||
aircraft: Optional[Aircraft] = strawberry.field(resolver=lambda root: aircraft_dataloader.load(root.aircraft_id))
|
||||
|
||||
|
||||
@strawberry_sqlalchemy_type(models.Copilot)
|
||||
|
||||
Reference in New Issue
Block a user