Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
901ebb8
UI for saving maps
categulario Feb 27, 2026
7539ef3
save maps (mostly)
categulario Mar 8, 2026
5e414e8
move api call to button component
categulario Mar 8, 2026
9dd1392
simplify the header by delegating its children to the callsite
categulario Mar 8, 2026
1bad964
save maps with a name
categulario Mar 8, 2026
894a43a
restore use of tag options in maps
categulario Mar 8, 2026
90b2eba
i18n for savemap dialog
categulario Mar 8, 2026
0b1f15b
set time since update in map list
categulario Mar 8, 2026
198114e
allow to delete maps from the list
categulario Mar 8, 2026
2d123ff
save a map's media
categulario Mar 10, 2026
2f53a7b
Merge branch 'develop' into feat/map-saving
categulario Mar 10, 2026
c22983d
progress bar in saving media
categulario Mar 10, 2026
95ace99
sort maps in descending chronological order
categulario Mar 10, 2026
7b004d9
delete obsolete experimental flag
categulario Mar 10, 2026
c7b8262
add minio container to dev compose file
categulario Mar 10, 2026
1fb7312
use docker hostname by default in settings
categulario Mar 10, 2026
d68435b
hide two buttons for now
categulario Mar 11, 2026
d846d90
fix variable for s3_endpoint url
categulario Mar 11, 2026
489f22e
ask for confirmation before deleting a map
categulario Mar 11, 2026
6d3b417
notify when trying to save without session
categulario Mar 12, 2026
d4eead9
remove console.log
categulario Mar 12, 2026
62f3a70
make own exports importable again
categulario Mar 12, 2026
35f3d0d
Merge branch 'develop' into feat/map-saving
categulario Mar 13, 2026
b498c98
link map list to the individual view
categulario Mar 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ media
certbot/
deploy/frontend/config.json
deploy/nginx/default.conf
hanko-config.yaml
34 changes: 34 additions & 0 deletions chatmap-api/alembic/versions/6d6a20ec27e1_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""empty message

Revision ID: 6d6a20ec27e1
Revises: 78016e58ae19
Create Date: 2026-03-08 15:44:43.615858

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '6d6a20ec27e1'
down_revision: Union[str, Sequence[str], None] = '78016e58ae19'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('maps', sa.Column('created_at', sa.DateTime(), nullable=False, server_default=sa.func.now()))
op.add_column('maps', sa.Column('updated_at', sa.DateTime(), nullable=False, server_default=sa.func.now()))
# ### end Alembic commands ###


def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('maps', 'updated_at')
op.drop_column('maps', 'created_at')
# ### end Alembic commands ###
32 changes: 32 additions & 0 deletions chatmap-api/alembic/versions/78016e58ae19_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""empty message

Revision ID: 78016e58ae19
Revises: 5d7e8452f39a
Create Date: 2026-03-04 20:01:23.972241

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '78016e58ae19'
down_revision: Union[str, Sequence[str], None] = '5d7e8452f39a'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('uq_maps_owner_id', 'maps', type_='unique')
# ### end Alembic commands ###


def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.create_unique_constraint("uq_maps_owner_id", "maps", ["owner_id"])
# ### end Alembic commands ###
47 changes: 4 additions & 43 deletions chatmap-api/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@
import uuid
import logging
from enum import Enum
from sqlalchemy import create_engine, Column, String, select, DateTime, text, ForeignKey, func, Enum as SqlEnum, UniqueConstraint
from sqlalchemy import create_engine, Column, String, select, DateTime, text, ForeignKey, func, Enum as SqlEnum
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.pool import NullPool
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import sessionmaker, declarative_base, Session, relationship
from geoalchemy2 import Geometry
from typing import Dict, List, Literal, Tuple
from settings import CHATMAP_DB, CHATMAP_DB_USER, CHATMAP_DB_PASSWORD, CHATMAP_DB_PORT, CHATMAP_DB_HOST
from datetime import datetime
from pydantic import BaseModel

# Logs
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -63,15 +61,14 @@ def __repr__(self) -> str:
# Model representing a user's map
class Map(Base):
__tablename__ = "maps"
__table_args__ = (
UniqueConstraint("owner_id", name="uq_maps_owner_id"),
)
id = Column(String, primary_key=True, index=True, default=lambda: str(uuid.uuid4()))
name = Column(String, default="Untitled")
sharing = Column(SqlEnum(SharePermission, name="sharing_permission"),
nullable=False,
default=SharePermission.PRIVATE)
owner_id = Column(String, nullable=False, index=True)
created_at = Column(DateTime(timezone=False), default=datetime.now, nullable=False)
updated_at = Column(DateTime(timezone=False), default=datetime.now, nullable=False)

# Relationship to Point model
points = relationship(
Expand Down Expand Up @@ -114,7 +111,7 @@ def get_or_create_map(db, user_id: str) -> str:
# Model representing a geographic point in a map
class Point(Base):
__tablename__ = "points"
id = Column(String, primary_key=True, index=True)
id = Column(String, primary_key=True, index=True, default=lambda: str(uuid.uuid4()))
geom = Column(Geometry(geometry_type="POINT", srid=4326)) # WGS84 coordinate system
message = Column(String)
username = Column(String)
Expand Down Expand Up @@ -154,42 +151,6 @@ def add_points(db: Session, points, user_id):
db.commit()


# Models for GeoJSON output
class FeatureGeometry(BaseModel):
"""
Represents the geometry of a GeoJSON feature (Point).
"""
type: Literal["Point"]
coordinates: Tuple[float, float] # GeoJSON is [lon, lat]

class FeatureProperties(BaseModel):
"""
Represents the properties of a GeoJSON feature.
"""
id: str
time: datetime
username_id: str
message: str | None = None
file: str | None

class Feature(BaseModel):
"""
Represents a GeoJSON feature.
"""
type: Literal["Feature"]
geometry: FeatureGeometry
properties: FeatureProperties

class FeatureCollection(BaseModel):
"""
Represents a GeoJSON FeatureCollection.
"""
id: str
sharing: str
name: str
type: Literal["FeatureCollection"]
features: List[Feature] = []

# Dependency to get a database session
def get_db_session():
"""
Expand Down
Loading