from sqlite3 import Row from typing import Any, Self, Tuple from uuid import uuid4 from flask import url_for from .exceptions import DatabaseException, ErrorException, NotFoundException from .record import BrickRecord from .sql import BrickSQL # Lego set checkbox class BrickSetCheckbox(BrickRecord): # Queries select_query: str = 'checkbox/select' def __init__( self, /, *, record: Row | dict[str, Any] | None = None, ): super().__init__() # Ingest the record if it has one if record is not None: self.ingest(record) # SQL column name def as_column(self) -> str: return 'status_{id}'.format(id=self.fields.id) # HTML dataset name def as_dataset(self) -> str: return '{id}'.format( id=self.as_column().replace('_', '-') ) # Delete from database def delete(self) -> None: BrickSQL().executescript( 'checkbox/delete', id=self.fields.id, ) # Grab data from a form def from_form(self, form: dict[str, str]) -> Self: name = form.get('name', None) grid = form.get('grid', None) if name is None or name == '': raise ErrorException('Checkbox name cannot be empty') # Security: eh. # Prevent self-ownage with accidental quote escape self.fields.name = name self.fields.safe_name = self.fields.name.replace("'", "''") self.fields.displayed_on_grid = grid == 'on' return self # Insert into database def insert(self, **_) -> Tuple[int, str]: # Generate an ID for the checkbox (with underscores to make it # column name friendly) self.fields.id = str(uuid4()).replace('-', '_') BrickSQL().executescript( 'checkbox/add', id=self.fields.id, name=self.fields.safe_name, displayed_on_grid=self.fields.displayed_on_grid ) # To accomodate the parent().insert we have overriden return 0, '' # Rename the checkbox def rename(self, /) -> None: # Update the name rows, _ = BrickSQL().execute_and_commit( 'checkbox/update/name', parameters=self.sql_parameters(), ) if rows != 1: raise DatabaseException('Could not update the name for checkbox {name} ({id})'.format( # noqa: E501 name=self.fields.name, id=self.fields.id, )) # URL to change the status def status_url(self, id: str) -> str: return url_for( 'set.update_status', id=id, checkbox_id=self.fields.id ) # Select a specific checkbox (with an id) def select_specific(self, id: str, /) -> Self: # Save the parameters to the fields self.fields.id = id # Load from database if not self.select(): raise NotFoundException( 'Checkbox with ID {id} was not found in the database'.format( id=self.fields.id, ), ) return self # Update a status def update_status( self, name: str, status: bool, / ) -> None: if not hasattr(self.fields, name) or name in ['id', 'name']: raise NotFoundException('{name} is not a field of a checkbox'.format( # noqa: E501 name=name )) parameters = self.sql_parameters() parameters['status'] = status # Update the status rows, _ = BrickSQL().execute_and_commit( 'checkbox/update/status', parameters=parameters, name=name, ) if rows != 1: raise DatabaseException('Could not update the status "{status}" for checkbox {name} ({id})'.format( # noqa: E501 status=name, name=self.fields.name, id=self.fields.id, ))