From e8e9a02e7b64fa8ee2ee4ba21cfd39323c2a3b24 Mon Sep 17 00:00:00 2001 From: Teddy Middleton-Smith Date: Sat, 28 Feb 2026 19:53:50 +0000 Subject: [PATCH] Feat: User Relationships and Session Members. --- app.py | 2 +- business_objects/base.py | 4 +- business_objects/sql_error.py | 8 +- business_objects/tcg/mtg_deck.py | 33 +- business_objects/tcg/mtg_game.py | 21 +- business_objects/tcg/mtg_game_player.py | 16 +- .../tcg/mtg_game_session_member.py | 194 +++ business_objects/tcg/user.py | 10 +- business_objects/tcg/user_relationship.py | 197 +++ config.py | 2 + controllers/tcg/mtg_game.py | 110 +- controllers/user/user.py | 39 +- datastores/datastore_base.py | 44 +- datastores/datastore_mtg.py | 105 +- datastores/datastore_user.py | 43 +- forms/tcg/game.py | 6 +- forms/tcg/user.py | 2 +- helpers/helper_app.py | 4 +- models/model_view_base.py | 2 +- models/model_view_mtg_base.py | 2 +- models/model_view_mtg_decks.py | 15 +- models/model_view_mtg_game.py | 6 +- models/model_view_mtg_games.py | 4 +- models/model_view_mtg_home.py | 2 +- models/model_view_user.py | 4 +- .../10508_tbl_TCG_User_Relationship.sql | 29 + .../10509_tbl_TCG_User_Relationship_Audit.sql | 15 + .../10510_tbl_TCG_User_Relationship_Temp.sql | 17 + ...rror_Type.sql => 10520_tbl_Error_Type.sql} | 0 ...dit.sql => 10521_tbl_Error_Type_Audit.sql} | 0 ...0514_tbl_Error.sql => 10524_tbl_Error.sql} | 0 ...or_Audit.sql => 10525_tbl_Error_Audit.sql} | 0 .../11152_tbl_TCG_MTG_Inventory_Temp.sql | 27 - .../11224_tbl_TCG_MTG_Game_Session_Member.sql | 28 + ..._tbl_TCG_MTG_Game_Session_Member_Audit.sql | 15 + ...6_tbl_TCG_MTG_Game_Session_Member_Temp.sql | 16 + .../30508_tri_TCG_User_Relationship.sql | 84 ++ .../31224_tri_TCG_MTG_Game_Session_Member.sql | 76 ++ .../PostgreSQL/70505_usp_TCG_User_Login.sql | 65 +- ...0508_fn_TCG_User_Relationship_Get_Many.sql | 131 ++ .../70509_usp_TCG_User_Relationship_Save.sql | 532 ++++++++ .../71150_usp_TCG_MTG_Inventory_Save.sql | 2 +- .../71200_fn_TCG_MTG_Deck_Get_Many.sql | 71 +- .../71208_fn_TCG_MTG_Game_Get_Many.sql | 4 + .../71212_fn_TCG_MTG_Game_Player_Get_Many.sql | 18 +- .../71213_usp_TCG_MTG_Game_Player_Save.sql | 353 ++++-- ...221_usp_TCG_MTG_Game_Round_Damage_Save.sql | 1068 +++++++++++++---- ...n_TCG_MTG_Game_Get_Many_Session_Member.sql | 140 +++ ...5_usp_TCG_MTG_Game_Session_Member_Save.sql | 532 ++++++++ .../71301_usp_TCG_Statistic_Calc.sql | 9 +- static/css/pages/tcg/decks.css | 3 +- static/css/pages/tcg/game.css | 16 +- static/css/sections/tcg.css | 3 +- static/dist/css/tcg_decks.bundle.css | 6 +- static/dist/css/tcg_decks.bundle.css.map | 2 +- static/dist/css/tcg_game.bundle.css | 19 +- static/dist/css/tcg_game.bundle.css.map | 2 +- static/dist/css/tcg_games.bundle.css | 3 +- static/dist/css/tcg_games.bundle.css.map | 2 +- static/dist/css/tcg_home.bundle.css | 3 +- static/dist/css/tcg_home.bundle.css.map | 2 +- static/dist/css/user_account.bundle.css | 3 +- static/dist/css/user_account.bundle.css.map | 2 +- static/dist/css/user_accounts.bundle.css | 3 +- static/dist/css/user_accounts.bundle.css.map | 2 +- static/dist/js/main.bundle.js | 83 +- static/dist/js/main.bundle.js.map | 2 +- static/js/api.js | 7 + static/js/pages/tcg/mtg_game.js | 76 +- templates/layouts/_shared_mtg_scripts.html | 1 + templates/layouts/_shared_scripts.html | 1 + templates/pages/tcg/mtg/_game.html | 18 +- todo.txt | 23 +- 73 files changed, 3818 insertions(+), 571 deletions(-) create mode 100644 business_objects/tcg/mtg_game_session_member.py create mode 100644 business_objects/tcg/user_relationship.py create mode 100644 static/PostgreSQL/10508_tbl_TCG_User_Relationship.sql create mode 100644 static/PostgreSQL/10509_tbl_TCG_User_Relationship_Audit.sql create mode 100644 static/PostgreSQL/10510_tbl_TCG_User_Relationship_Temp.sql rename static/PostgreSQL/{10510_tbl_Error_Type.sql => 10520_tbl_Error_Type.sql} (100%) rename static/PostgreSQL/{10511_tbl_Error_Type_Audit.sql => 10521_tbl_Error_Type_Audit.sql} (100%) rename static/PostgreSQL/{10514_tbl_Error.sql => 10524_tbl_Error.sql} (100%) rename static/PostgreSQL/{10515_tbl_Error_Audit.sql => 10525_tbl_Error_Audit.sql} (100%) create mode 100644 static/PostgreSQL/11224_tbl_TCG_MTG_Game_Session_Member.sql create mode 100644 static/PostgreSQL/11225_tbl_TCG_MTG_Game_Session_Member_Audit.sql create mode 100644 static/PostgreSQL/11226_tbl_TCG_MTG_Game_Session_Member_Temp.sql create mode 100644 static/PostgreSQL/30508_tri_TCG_User_Relationship.sql create mode 100644 static/PostgreSQL/31224_tri_TCG_MTG_Game_Session_Member.sql create mode 100644 static/PostgreSQL/70508_fn_TCG_User_Relationship_Get_Many.sql create mode 100644 static/PostgreSQL/70509_usp_TCG_User_Relationship_Save.sql create mode 100644 static/PostgreSQL/71224_fn_TCG_MTG_Game_Get_Many_Session_Member.sql create mode 100644 static/PostgreSQL/71225_usp_TCG_MTG_Game_Session_Member_Save.sql diff --git a/app.py b/app.py index bbb70dd..7eaec7a 100644 --- a/app.py +++ b/app.py @@ -49,7 +49,7 @@ app.app_config = app_config # app.config["config"] = app_config() # logging -handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=3) +handler = RotatingFileHandler('app.log', maxBytes=10_000_000, backupCount=16) handler.setLevel(logging.DEBUG) app.logger.addHandler(handler) diff --git a/business_objects/base.py b/business_objects/base.py index e664245..ce4fc12 100644 --- a/business_objects/base.py +++ b/business_objects/base.py @@ -38,7 +38,7 @@ class Base(): FLAG_CITY: ClassVar[str] = 'city' FLAG_CODE: ClassVar[str] = 'code' FLAG_COUNTY: ClassVar[str] = 'county' - FLAG_CREATED_BY: ClassVar[str] = 'created_by' + FLAG_CREATED_BY_USER_ID: ClassVar[str] = 'created_by_user_id' FLAG_CREATED_ON: ClassVar[str] = 'created_on' FLAG_CURRENCY: ClassVar[str] = 'currency' FLAG_CURRENCY_COST: ClassVar[str] = 'currency_cost' @@ -74,6 +74,8 @@ class Base(): FLAG_SURNAME: ClassVar[str] = 'surname' FLAG_SYMBOL: ClassVar[str] = 'symbol' FLAG_TEXT_COLOUR: ClassVar[str] = 'text_colour' + FLAG_UPDATED_LAST_BY_USER_ID: ClassVar[str] = 'updated_last_by_user_id' + FLAG_UPDATED_LAST_ON: ClassVar[str] = 'updated_last_on' FLAG_URL: ClassVar[str] = 'url' FLAG_USER: ClassVar[str] = 'authorisedUser' # 'user' already used FLAG_VALUE: ClassVar[str] = 'value' diff --git a/business_objects/sql_error.py b/business_objects/sql_error.py index 9e75f8e..8dc1162 100644 --- a/business_objects/sql_error.py +++ b/business_objects/sql_error.py @@ -52,8 +52,8 @@ class SQL_Error(SQLAlchemy_ABC, Base): @classmethod def from_db_error(cls, record): _m = f'{cls.__qualname__}.from_db_error' - Helper_App.console_log(_m) - Helper_App.console_log(f'record: {record}') + # Helper_App.console_log(_m) + # Helper_App.console_log(f'record: {record}') error = cls() error.error_id = record[0] error.guid = record[1] @@ -68,14 +68,14 @@ class SQL_Error(SQLAlchemy_ABC, Base): @classmethod def from_exception(cls, exception: Exception, is_breaking: bool = True): _m = f'{cls.__qualname__}.from_exception' - Helper_App.console_log(_m) + # Helper_App.console_log(_m) error = cls() error.error_id = -1 error.id_type = -1 error.code_type = type(exception).__name__ error.name_type = type(exception).__name__ error.msg = str(exception) - Helper_App.console_log(f'Error: {error}') + # Helper_App.console_log(f'Error: {error}') return error @classmethod diff --git a/business_objects/tcg/mtg_deck.py b/business_objects/tcg/mtg_deck.py index 56db93e..849af69 100644 --- a/business_objects/tcg/mtg_deck.py +++ b/business_objects/tcg/mtg_deck.py @@ -114,24 +114,34 @@ class Parameters_MTG_Deck(Get_Many_Parameters_Base): deck_names: str commander_bracket_ids: str include_commander_option: bool + created_by_user_ids: str + get_all_game: bool + get_inactive_game: bool + game_ids: str + filter_by_game_session_not_player: bool require_all_id_filters_met: bool require_any_id_filters_met: bool require_all_non_id_filters_met: bool require_any_non_id_filters_met: bool @classmethod - def get_default(cls): + def get_default(cls, user_id): return cls( - get_all_deck = True + get_all_deck = False , get_inactive_deck = False , deck_ids = '' , deck_names = '' , commander_bracket_ids = '' , include_commander_option = True - , require_all_id_filters_met = True + , created_by_user_ids = str(user_id) + , get_all_game = False + , get_inactive_game = False + , game_ids = '' + , filter_by_game_session_not_player = False + , require_all_id_filters_met = False , require_any_id_filters_met = True , require_all_non_id_filters_met = False - , require_any_non_id_filters_met = True + , require_any_non_id_filters_met = False ) @classmethod @@ -143,6 +153,11 @@ class Parameters_MTG_Deck(Get_Many_Parameters_Base): , deck_names = json.get('a_deck_names', '') , commander_bracket_ids = json.get('a_commander_bracket_ids', '') , include_commander_option = json.get('a_include_commander_option', True) + , created_by_user_ids = json.get('a_created_by_user_ids', '') + , get_all_game = json.get('a_get_all_game', False) + , get_inactive_game = json.get('a_get_inactive_game', False) + , game_ids = json.get('a_game_ids', '') + , filter_by_game_session_not_player = json.get('a_filter_by_game_session_not_player', True) , require_all_id_filters_met = json.get('a_require_all_id_filters_met', True) , require_any_id_filters_met = json.get('a_require_any_id_filters_met', True) , require_all_non_id_filters_met = json.get('a_require_all_non_id_filters_met', False) @@ -157,6 +172,11 @@ class Parameters_MTG_Deck(Get_Many_Parameters_Base): , 'a_deck_names': self.deck_names , 'a_commander_bracket_ids': self.commander_bracket_ids , 'a_include_commander_option': self.include_commander_option + , 'a_created_by_user_ids': self.created_by_user_ids + , 'a_get_all_game': self.get_all_game + , 'a_get_inactive_game': self.get_inactive_game + , 'a_game_ids': self.game_ids + , 'a_filter_by_game_session_not_player': self.filter_by_game_session_not_player , 'a_require_all_id_filters_met': self.require_all_id_filters_met , 'a_require_any_id_filters_met': self.require_any_id_filters_met , 'a_require_all_non_id_filters_met': self.require_all_non_id_filters_met @@ -172,6 +192,11 @@ class Parameters_MTG_Deck(Get_Many_Parameters_Base): , 'a_deck_names': Text , 'a_commander_bracket_ids': Text , 'a_include_commander_option': Boolean + , 'a_created_by_user_ids': Text + , 'a_get_all_game': Boolean + , 'a_get_inactive_game': Boolean + , 'a_game_ids': Text + , 'a_filter_by_game_session_not_player': Boolean , 'a_require_all_id_filters_met': Boolean , 'a_require_any_id_filters_met': Boolean , 'a_require_all_non_id_filters_met': Boolean diff --git a/business_objects/tcg/mtg_game.py b/business_objects/tcg/mtg_game.py index 05ad2a1..68ee1ac 100644 --- a/business_objects/tcg/mtg_game.py +++ b/business_objects/tcg/mtg_game.py @@ -14,6 +14,7 @@ import lib.argument_validation as av from extensions import db from helpers.helper_app import Helper_App # external +from datetime import datetime from dataclasses import dataclass from typing import ClassVar from sqlalchemy import bindparam @@ -74,6 +75,8 @@ class MTG_Game(SQLAlchemy_ABC, Base): game.active = av.input_bool(query_row[9], cls.FLAG_ACTIVE, _m) game.created_on = query_row[10] game.created_by_user_id = query_row[11] + game.updated_last_on = query_row[12] + game.updated_last_by_user_id = query_row[13] return game @classmethod @@ -91,8 +94,16 @@ class MTG_Game(SQLAlchemy_ABC, Base): game.starting_life = json.get(cls.FLAG_STARTING_LIFE, 40) game.end_on = json.get(cls.FLAG_END_ON, None) game.active = av.input_bool(json.get(cls.FLAG_ACTIVE, True), cls.FLAG_ACTIVE, _m) - game.created_on = json.get(cls.FLAG_CREATED_ON, None) + _created_on = json.get(Base.FLAG_CREATED_ON, None) + if isinstance(_created_on, str): + _created_on = datetime.strptime(_created_on, '%a, %d %b %Y %H:%M:%S %Z') + game.created_on = _created_on game.created_by_user_id = json.get(Base.ATTR_USER_ID, None) + _updated_last_on = json.get(Base.FLAG_UPDATED_LAST_ON, None) + if isinstance(_updated_last_on, str): + _updated_last_on = datetime.strptime(_updated_last_on, '%a, %d %b %Y %H:%M:%S %Z') + game.updated_last_on = _updated_last_on + game.updated_last_by_user_id = json.get(Base.FLAG_UPDATED_LAST_BY_USER_ID, None) return game def to_json(self): @@ -109,7 +120,9 @@ class MTG_Game(SQLAlchemy_ABC, Base): , self.FLAG_END_ON: self.end_on , self.FLAG_ACTIVE: self.active , self.FLAG_CREATED_ON: self.created_on - , Base.ATTR_USER_ID: self.created_by_user_id + , self.FLAG_CREATED_BY_USER_ID: self.created_by_user_id + , self.FLAG_UPDATED_LAST_ON: self.updated_last_on + , self.FLAG_UPDATED_LAST_BY_USER_ID: self.updated_last_by_user_id } return as_json @@ -127,7 +140,9 @@ class MTG_Game(SQLAlchemy_ABC, Base): {self.FLAG_STARTING_LIFE}: {self.starting_life} {self.FLAG_ACTIVE}: {self.active} {self.FLAG_CREATED_ON}: {self.created_on} - {Base.ATTR_USER_ID}: {self.created_by_user_id} + {self.FLAG_CREATED_BY_USER_ID}: {self.created_by_user_id} + {self.FLAG_UPDATED_LAST_ON}: {self.updated_last_on} + {self.FLAG_UPDATED_LAST_BY_USER_ID}: {self.updated_last_by_user_id} ) ''' diff --git a/business_objects/tcg/mtg_game_player.py b/business_objects/tcg/mtg_game_player.py index ca9080e..ce1b67f 100644 --- a/business_objects/tcg/mtg_game_player.py +++ b/business_objects/tcg/mtg_game_player.py @@ -10,6 +10,8 @@ Feature: MTG Game Player Business Object # internal from business_objects.base import Base from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base +from business_objects.tcg.mtg_deck import MTG_Deck +from business_objects.tcg.mtg_game import MTG_Game import lib.argument_validation as av from extensions import db from helpers.helper_app import Helper_App @@ -22,8 +24,6 @@ from sqlalchemy.types import Text, Boolean class MTG_Game_Player(SQLAlchemy_ABC, Base): ATTR_PLAYER_ID: ClassVar[str] = 'player_id' - ATTR_GAME_ID: ClassVar[str] = 'game_id' - ATTR_DECK_ID: ClassVar[str] = 'deck_id' FLAG_PLAYER: ClassVar[str] = 'player' FLAG_NOTES: ClassVar[str] = 'notes' FLAG_DISPLAY_ORDER: ClassVar[str] = 'display_order' @@ -74,9 +74,9 @@ class MTG_Game_Player(SQLAlchemy_ABC, Base): player = cls() if json is None: return player player.player_id = json.get(cls.ATTR_PLAYER_ID, -1) - player.game_id = json.get(cls.ATTR_GAME_ID, None) + player.game_id = json.get(MTG_Game.ATTR_GAME_ID, None) player.user_id = json.get(Base.ATTR_USER_ID, None) - player.deck_id = json.get(cls.ATTR_DECK_ID, None) + player.deck_id = json.get(MTG_Deck.ATTR_DECK_ID, None) player.name = json.get(cls.FLAG_NAME, None) player.notes = json.get(cls.FLAG_NOTES, None) player.display_order = json.get(cls.FLAG_DISPLAY_ORDER, 0) @@ -89,9 +89,9 @@ class MTG_Game_Player(SQLAlchemy_ABC, Base): as_json = { **self.get_shared_json_attributes(self) , self.ATTR_PLAYER_ID: self.player_id - , self.ATTR_GAME_ID: self.game_id + , MTG_Game.ATTR_GAME_ID: self.game_id , Base.ATTR_USER_ID: self.user_id - , self.ATTR_DECK_ID: self.deck_id + , MTG_Deck.ATTR_DECK_ID: self.deck_id , self.FLAG_NAME: self.name , self.FLAG_NOTES: self.notes , self.FLAG_DISPLAY_ORDER: self.display_order @@ -104,9 +104,9 @@ class MTG_Game_Player(SQLAlchemy_ABC, Base): return f''' {self.__class__.__name__}( {self.ATTR_PLAYER_ID}: {self.player_id} - {self.ATTR_GAME_ID}: {self.game_id} + {MTG_Game.ATTR_GAME_ID}: {self.game_id} {Base.ATTR_USER_ID}: {self.user_id} - {self.ATTR_DECK_ID}: {self.deck_id} + {MTG_Deck.ATTR_DECK_ID}: {self.deck_id} {self.FLAG_NAME}: {self.name} {self.FLAG_NOTES}: {self.notes} {self.FLAG_DISPLAY_ORDER}: {self.display_order} diff --git a/business_objects/tcg/mtg_game_session_member.py b/business_objects/tcg/mtg_game_session_member.py new file mode 100644 index 0000000..b3f3c0c --- /dev/null +++ b/business_objects/tcg/mtg_game_session_member.py @@ -0,0 +1,194 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: MTG Game Session Member Business Object +""" + +# internal +from business_objects.base import Base +from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base +from business_objects.tcg.mtg_game import MTG_Game +from business_objects.tcg.user import User +import lib.argument_validation as av +from extensions import db +from helpers.helper_app import Helper_App +# external +from dataclasses import dataclass +from typing import ClassVar +from sqlalchemy import Uuid +from sqlalchemy.types import Text, Boolean +# import uuid + +class MTG_Game_Session_Member(SQLAlchemy_ABC, Base): + ATTR_SESSION_MEMBER_ID: ClassVar[str] = 'member_id' + FLAG_IS_PERMITTED: ClassVar[str] = 'is_permitted' + NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_SESSION_MEMBER_ID + NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME + + __tablename__ = 'tcg_mtg_game_session_member' + __table_args__ = { 'extend_existing': True } + + member_id = db.Column(db.Integer, primary_key=True) + game_id = db.Column(db.Integer) + user_id = db.Column(db.Integer) + is_permitted = db.Column(db.Boolean) + active = db.Column(db.Boolean) + created_on = db.Column(db.DateTime) + created_by_user_id = db.Column(db.Integer) + updated_last_on = db.Column(db.DateTime) + updated_last_by_user_id = db.Column(db.Integer) + change_set_id = db.Column(db.Integer) + + def __init__(self): + self.member_id = 0 + self.is_new = False + super().__init__() + + @classmethod + def from_db_mtg_game_player(cls, query_row): + _m = f'{cls.__qualname__}.from_db_mtg_game_player' + player = cls() + player.member_id = query_row[0] + player.game_id = query_row[1] + player.user_id = query_row[2] + player.is_permitted = query_row[3] + player.active = av.input_bool(query_row[4], cls.FLAG_ACTIVE, _m) + player.created_on = query_row[5] + player.created_by_user_id = query_row[6] + return player + + @classmethod + def from_json(cls, json): + _m = f'{cls.__qualname__}.from_json' + player = cls() + if json is None: return player + player.member_id = json.get(cls.ATTR_SESSION_MEMBER_ID, -1) + player.game_id = json.get(MTG_Game.ATTR_GAME_ID, None) + player.user_id = json.get(Base.ATTR_USER_ID, None) + player.is_permitted = json.get(cls.FLAG_IS_PERMITTED, None) + player.active = av.input_bool(json.get(cls.FLAG_ACTIVE, True), cls.FLAG_ACTIVE, _m) + player.created_on = json.get(cls.FLAG_CREATED_ON, None) + player.created_by_user_id = json.get(Base.ATTR_USER_ID, None) + return player + + def to_json(self): + as_json = { + **self.get_shared_json_attributes(self) + , self.ATTR_SESSION_MEMBER_ID: self.member_id + , MTG_Game.ATTR_GAME_ID: self.game_id + , Base.ATTR_USER_ID: self.user_id + , self.FLAG_IS_PERMITTED: self.is_permitted + , self.FLAG_ACTIVE: self.active + , self.FLAG_CREATED_ON: self.created_on + } + return as_json + + def __repr__(self): + return f''' +{self.__class__.__name__}( + {self.ATTR_SESSION_MEMBER_ID}: {self.member_id} + {MTG_Game.ATTR_GAME_ID}: {self.game_id} + {Base.ATTR_USER_ID}: {self.user_id} + {self.FLAG_IS_PERMITTED}: {self.is_permitted} + {self.FLAG_ACTIVE}: {self.active} + {self.FLAG_CREATED_ON}: {self.created_on} +) + ''' + +class MTG_Game_Session_Member_Temp(db.Model, Base): + __tablename__ = 'tcg_mtg_game_session_member_temp' + __table_args__ = { 'extend_existing': True } + temp_id = db.Column(db.Integer, primary_key=True) + member_id = db.Column(db.Integer) + game_id = db.Column(db.Integer) + user_id = db.Column(db.Integer) + is_permitted = db.Column(db.Boolean) + active = db.Column(db.Boolean) + created_on = db.Column(db.DateTime) + guid = db.Column(Uuid) #, default = uuid.uuid4) + + def __init__(self): + super().__init__() + + @classmethod + def from_session_member(cls, member, guid): + _m = 'MTG_Game_Session_Member_Temp.from_session_member' + temp = cls() + temp.member_id = member.member_id + temp.game_id = member.game_id + temp.user_id = member.user_id + temp.is_permitted = member.is_permitted + temp.active = member.active + temp.created_on = member.created_on + temp.guid = guid + return temp + + +class Parameters_MTG_Game_Session_Member(Get_Many_Parameters_Base): + get_inactive_session_member: bool + get_all_game: bool + get_inactive_game: bool + game_ids: str + get_all_user: bool + get_inactive_user: bool + user_ids: str + require_all_id_filters_met: bool + require_any_id_filters_met: bool + + @classmethod + def get_default(cls, user_id_session): + return cls( + get_inactive_session_member = False + , get_all_game = True + , get_inactive_game = False + , game_ids = '' + , get_all_user = True + , get_inactive_user = False + , user_ids = str(user_id_session) + , require_all_id_filters_met = True + , require_any_id_filters_met = True + ) + + @classmethod + def from_json(cls, json): + return cls( + get_inactive_session_member = json.get('a_get_inactive_session_member', False) + , get_all_game = json.get('a_get_all_game', False) + , get_inactive_game = json.get('a_get_inactive_game', False) + , game_ids = json.get('a_game_ids', '') + , get_all_user = json.get('a_get_all_user', False) + , get_inactive_user = json.get('a_get_inactive_user', False) + , user_ids = json.get('a_user_ids', '') + , require_all_id_filters_met = json.get('a_require_all_id_filters_met', True) + , require_any_id_filters_met = json.get('a_require_any_id_filters_met', True) + ) + + def to_json(self): + return { + 'a_get_inactive_session_member': self.get_inactive_session_member + , 'a_get_all_game': self.get_all_game + , 'a_get_inactive_game': self.get_inactive_game + , 'a_game_ids': self.game_ids + , 'a_get_all_user': self.get_all_user + , 'a_get_inactive_user': self.get_inactive_user + , 'a_user_ids': self.user_ids + , 'a_require_all_id_filters_met': self.require_all_id_filters_met + , 'a_require_any_id_filters_met': self.require_any_id_filters_met + } + + @staticmethod + def get_type_hints(): + return { + 'a_get_inactive_session_member': Boolean + , 'a_get_all_game': Boolean + , 'a_get_inactive_game': Boolean + , 'a_game_ids': Text + , 'a_get_all_user': Boolean + , 'a_get_inactive_user': Boolean + , 'a_user_ids': Text + , 'a_require_all_id_filters_met': Boolean + , 'a_require_any_id_filters_met': Boolean + } diff --git a/business_objects/tcg/user.py b/business_objects/tcg/user.py index 8ae8484..1914411 100644 --- a/business_objects/tcg/user.py +++ b/business_objects/tcg/user.py @@ -55,7 +55,7 @@ class User(SQLAlchemy_ABC, Base): updated_last_by_user_id, change_set_id """ _m = f'{cls.__qualname__}.from_db_user' - Helper_App.console_log(f'user record: {query_row}') + # Helper_App.console_log(f'user record: {query_row}') user = cls() user.user_id = query_row[0] user.user_auth0_id = query_row[1] @@ -72,7 +72,7 @@ class User(SQLAlchemy_ABC, Base): _m = f'{cls.__qualname__}.from_json' user = cls() if json is None: return user - Helper_App.console_log(f'{_m}/n{json}') + # Helper_App.console_log(f'{_m}/n{json}') user.user_id = json[cls.ATTR_USER_ID] user.user_auth0_id = json[cls.ATTR_USER_AUTH0_ID] user.firstname = json[cls.FLAG_FIRSTNAME] @@ -85,12 +85,12 @@ class User(SQLAlchemy_ABC, Base): @classmethod def from_json_auth0(cls, json): _m = f'{cls.__qualname__}.from_json_auth0' - Helper_App.console_log(_m) - Helper_App.console_log(f'JSON: {json}') + # Helper_App.console_log(_m) + # Helper_App.console_log(f'JSON: {json}') user = cls() if json is None: return user user_info = json['userinfo'] - Helper_App.console_log(f'user_info: {user_info}') + # Helper_App.console_log(f'user_info: {user_info}') user.user_id = None user.user_auth0_id = user_info['sub'] user.firstname = None diff --git a/business_objects/tcg/user_relationship.py b/business_objects/tcg/user_relationship.py new file mode 100644 index 0000000..8abe961 --- /dev/null +++ b/business_objects/tcg/user_relationship.py @@ -0,0 +1,197 @@ +""" +Project: PARTS Website +Author: Edward Middleton-Smith + Precision And Research Technology Systems Limited + +Technology: Business Objects +Feature: User Relationship Business Object +""" + +# internal +from business_objects.base import Base +from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base +import lib.argument_validation as av +from extensions import db +from helpers.helper_app import Helper_App +# external +from dataclasses import dataclass +from typing import ClassVar +from sqlalchemy import Uuid +from sqlalchemy.types import Text, Boolean +# import uuid + +class User_Relationship(SQLAlchemy_ABC, Base): + ATTR_RELATIONSHIP_ID: ClassVar[str] = 'relationship_id' + FLAG_FOLLOWER_USER_ID: ClassVar[str] = 'follower_user_id' + FLAG_FOLLOWING_USER_ID: ClassVar[str] = 'following_user_id' + FLAG_IS_FOLLOWING: ClassVar[str] = 'is_following' + FLAG_IS_BLOCKED: ClassVar[str] = 'is_blocked' + NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_RELATIONSHIP_ID + NAME_ATTR_OPTION_TEXT: ClassVar[str] = ATTR_RELATIONSHIP_ID + + __tablename__ = 'tcg_user_relationship' + __table_args__ = { 'extend_existing': True } + + relationship_id = db.Column(db.Integer, primary_key=True) + follower_user_id = db.Column(db.Integer) + following_user_id = db.Column(db.Integer) + is_following = db.Column(db.Boolean) + is_blocked = db.Column(db.Boolean) + active = db.Column(db.Boolean) + created_on = db.Column(db.DateTime) + created_by_user_id = db.Column(db.Integer) + updated_last_on = db.Column(db.DateTime) + updated_last_by_user_id = db.Column(db.Integer) + change_set_id = db.Column(db.Integer) + + def __init__(self): + self.relationship_id = 0 + self.is_new = False + super().__init__() + + @classmethod + def from_db_user_relationship(cls, query_row): + _m = f'{cls.__qualname__}.from_db_user_relationship' + player = cls() + player.relationship_id = query_row[0] + player.follower_user_id = query_row[1] + player.following_user_id = query_row[2] + player.is_following = query_row[3] + player.is_blocked = query_row[4] + player.active = av.input_bool(query_row[5], cls.FLAG_ACTIVE, _m) + player.created_on = query_row[6] + player.created_by_user_id = query_row[7] + return player + + @classmethod + def from_json(cls, json): + _m = f'{cls.__qualname__}.from_json' + player = cls() + if json is None: return player + player.relationship_id = json.get(cls.ATTR_RELATIONSHIP_ID, -1) + player.follower_user_id = json.get(cls.FLAG_FOLLOWER_USER_ID, None) + player.following_user_id = json.get(cls.FLAG_FOLLOWING_USER_ID, None) + player.is_following = json.get(cls.FLAG_IS_FOLLOWING, None) + player.is_blocked = json.get(cls.FLAG_IS_BLOCKED, None) + player.active = av.input_bool(json.get(cls.FLAG_ACTIVE, True), cls.FLAG_ACTIVE, _m) + player.created_on = json.get(cls.FLAG_CREATED_ON, None) + player.created_by_user_id = json.get(Base.ATTR_USER_ID, None) + return player + + def to_json(self): + as_json = { + **self.get_shared_json_attributes(self) + , self.ATTR_RELATIONSHIP_ID: self.relationship_id + , self.FLAG_FOLLOWER_USER_ID: self.follower_user_id + , self.FLAG_FOLLOWING_USER_ID: self.following_user_id + , self.FLAG_IS_FOLLOWING: self.is_following + , self.FLAG_IS_BLOCKED: self.is_blocked + , self.FLAG_ACTIVE: self.active + , self.FLAG_CREATED_ON: self.created_on + } + return as_json + + def __repr__(self): + return f''' +{self.__class__.__name__}( + {self.ATTR_RELATIONSHIP_ID}: {self.relationship_id} + {self.FLAG_FOLLOWER_USER_ID}: {self.follower_user_id} + {self.FLAG_FOLLOWING_USER_ID}: {self.following_user_id} + {self.FLAG_IS_FOLLOWING}: {self.is_following} + {self.FLAG_IS_BLOCKED}: {self.is_blocked} + {self.FLAG_ACTIVE}: {self.active} + {self.FLAG_CREATED_ON}: {self.created_on} +) + ''' + +class User_Relationship_Temp(db.Model, Base): + __tablename__ = 'tcg_user_relationship_temp' + __table_args__ = { 'extend_existing': True } + temp_id = db.Column(db.Integer, primary_key=True) + relationship_id = db.Column(db.Integer) + follower_user_id = db.Column(db.Integer) + following_user_id = db.Column(db.Integer) + is_following = db.Column(db.Boolean) + is_blocked = db.Column(db.Boolean) + active = db.Column(db.Boolean) + created_on = db.Column(db.DateTime) + guid = db.Column(Uuid) #, default = uuid.uuid4) + + def __init__(self): + super().__init__() + + @classmethod + def from_user_relationship(cls, relationship, guid): + _m = 'User_Relationship_Temp.from_user_relationship' + temp = cls() + temp.relationship_id = relationship.relationship_id + temp.follower_user_id = relationship.follower_user_id + temp.following_user_id = relationship.following_user_id + temp.is_following = relationship.is_following + temp.is_blocked = relationship.is_blocked + temp.active = relationship.active + temp.created_on = relationship.created_on + temp.guid = guid + return temp + + +class Parameters_User_Relationship(Get_Many_Parameters_Base): + get_inactive_user_relationship: bool + get_all_user_follower: bool + follower_user_ids: str + get_all_user_following: bool + following_user_ids: str + get_inactive_user: bool + require_all_id_filters_met: bool + require_any_id_filters_met: bool + + @classmethod + def get_default(cls, user_id_session): + return cls( + get_inactive_user_relationship = True + , get_all_user_follower = False + , follower_user_ids = '' + , get_all_user_following = True + , following_user_ids = '' + , get_inactive_user = False + , require_all_id_filters_met = True + , require_any_id_filters_met = True + ) + + @classmethod + def from_json(cls, json): + return cls( + get_inactive_user_relationship = json.get('a_get_inactive_user_relationship', False) + , get_all_user_follower = json.get('a_get_all_user_follower', False) + , follower_user_ids = json.get('a_follower_user_ids', '') + , get_all_user_following = json.get('a_get_all_user_following', False) + , following_user_ids = json.get('a_following_user_ids', '') + , get_inactive_user = json.get('a_get_inactive_user', False) + , require_all_id_filters_met = json.get('a_require_all_id_filters_met', True) + , require_any_id_filters_met = json.get('a_require_any_id_filters_met', True) + ) + + def to_json(self): + return { + 'a_get_inactive_user_relationship': self.get_inactive_user_relationship + , 'a_get_all_user_follower': self.get_all_user_follower + , 'a_follower_user_ids': self.follower_user_ids + , 'a_get_all_user_following': self.get_all_user_following + , 'a_following_user_ids': self.following_user_ids + , 'a_get_inactive_user': self.get_inactive_user + , 'a_require_all_id_filters_met': self.require_all_id_filters_met + , 'a_require_any_id_filters_met': self.require_any_id_filters_met + } + + @staticmethod + def get_type_hints(): + return { + 'a_get_inactive_user_relationship': Boolean + , 'a_get_all_user_follower': Boolean + , 'a_follower_user_ids': Text + , 'a_get_all_user_following': Boolean + , 'a_following_user_ids': Text + , 'a_get_inactive_user': Boolean + , 'a_require_all_id_filters_met': Boolean + , 'a_require_any_id_filters_met': Boolean + } diff --git a/config.py b/config.py index 1e4ed9f..243e1c4 100644 --- a/config.py +++ b/config.py @@ -105,10 +105,12 @@ class ProductionConfig(Config): # Set the configuration class based on the environment # You can change 'development' to 'production' when deploying config_env = os.getenv('FLASK_ENV', "development") +""" with open('app.log', 'a') as f: print(f'config_env: {config_env}') f.write(f'config_env: {config_env}\n') # current_app.logger.error(f'config_env: {config_env}') # logger not yet initialised +""" if config_env == 'development': app_config = DevelopmentConfig elif config_env == 'production': diff --git a/controllers/tcg/mtg_game.py b/controllers/tcg/mtg_game.py index a4e1dbb..deb7194 100644 --- a/controllers/tcg/mtg_game.py +++ b/controllers/tcg/mtg_game.py @@ -14,7 +14,7 @@ MTG Game Page Controller. # internal from business_objects.api import API from business_objects.tcg.mtg_deck import MTG_Deck -from business_objects.tcg.mtg_game import MTG_Game +from business_objects.tcg.mtg_game import MTG_Game, Parameters_MTG_Game from business_objects.tcg.mtg_game_player import MTG_Game_Player, Parameters_MTG_Game_Player from business_objects.tcg.mtg_game_round import MTG_Game_Round, Parameters_MTG_Game_Round from business_objects.tcg.mtg_game_round_player_damage import MTG_Game_Round_Player_Damage, Parameters_MTG_Game_Round_Player_Damage @@ -50,14 +50,14 @@ routes_mtg_game = Blueprint('routes_mtg_game', __name__) @routes_mtg_game.route(Model_View_MTG_Base.HASH_PAGE_MTG_GAMES, methods=['GET']) def games(): - Helper_App.console_log('mtg games') - Helper_App.console_log(f'request_args: {request.args}') + # Helper_App.console_log('mtg games') + # Helper_App.console_log(f'request_args: {request.args}') try: form_filters = Filters_MTG_Game.from_json(request.args) except Exception as e: - Helper_App.console_log(f'Error: {e}') + # Helper_App.console_log(f'Error: {e}') form_filters = Filters_MTG_Game() - Helper_App.console_log(f'form_filters={form_filters}') + # Helper_App.console_log(f'form_filters={form_filters}') datastore = DataStore_MTG() user_session = datastore.get_user_session() @@ -68,13 +68,13 @@ def games(): model = Model_View_MTG_Games(parameters_game = parameters_game) model.form_filters = form_filters - Helper_App.console_log(f'form_filters={form_filters}') + # Helper_App.console_log(f'form_filters={form_filters}') return render_template('pages/tcg/mtg/_games.html', model=model) @routes_mtg_game.route(f'{Model_View_MTG_Base.HASH_PAGE_MTG_GAME}/', methods=['GET']) def game_detail(game_id): - Helper_App.console_log(f'mtg game detail: {game_id}') + # Helper_App.console_log(f'mtg game detail: {game_id}') model = Model_View_MTG_Game(game_id=game_id) if not model.is_user_logged_in: return redirect(url_for('routes_mtg_game.home')) @@ -88,7 +88,7 @@ def game_detail(game_id): def save_game(): _m = 'routes_mtg_game.save_game' data = Helper_App.get_request_data(request) - Helper_App.console_log(f'{_m}\n{data}') + # Helper_App.console_log(f'{_m}\n{data}') try: """ form_filters = Filters_MTG_Game.from_json(data.get(Model_View_MTG_Base.FLAG_FORM_FILTERS, {})) @@ -111,10 +111,10 @@ def save_game(): Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: 'No games to save.' }) - Helper_App.console_log(f"Games to save: {games}") + # Helper_App.console_log(f"Games to save: {games}") obj_game = MTG_Game.from_json(games[0]) - Helper_App.console_log(f'obj_game={obj_game}') + # Helper_App.console_log(f'obj_game={obj_game}') game_id, errors = DataStore_MTG.save_mtg_game(obj_game) @@ -148,11 +148,69 @@ def trial_game(): return send_from_directory('templates/pages/tcg/mtg', 'trial_game.html') +@routes_mtg_game.route('/mtg/api/game//is-outdated', methods=['POST']) +def get_is_game_data_outdated(game_id): + """Check if saved game has been updated since page load.""" + _m = 'routes_mtg_game.get_is_game_data_outdated' + # Helper_App.console_log(f'{_m}: game_id={game_id}') + data = Helper_App.get_request_data(request) + # Helper_App.console_log(f'{_m}\n{data}') + try: + loaded_game = data.get(Model_View_MTG_Base.FLAG_GAME, None) + if loaded_game is None: + return jsonify({ + Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE + , Model_View_MTG_Base.FLAG_MESSAGE: 'Loaded game not sent for comparison.' + }) + # Helper_App.console_log(f"Loaded game: {loaded_game}") + + obj_loaded_game = MTG_Game.from_json(loaded_game) + # Helper_App.console_log(f'obj_loaded_game={obj_loaded_game}') + + datastore = DataStore_MTG() + user_session = datastore.get_user_session() + + if not user_session.get_is_logged_in(): + return jsonify({ + Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE + , Model_View_MTG_Base.FLAG_MESSAGE: 'User not logged in' + }), 401 + + # Get saved game + parameters_game = Parameters_MTG_Game.get_default(user_session.user_id) + parameters_game.game_ids = str(game_id) + parameters_game.get_all_game = False + saved_games, errors = datastore.get_many_mtg_game(parameters_game) + + if (len(errors) > 0 or len(saved_games) == 0): + return jsonify({ + Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE + , Model_View_MTG_Base.FLAG_MESSAGE: f'Error fetching saved game: {errors}' + }), 500 + + saved_game = saved_games[0] + saved_game.updated_last_on = saved_game.updated_last_on.replace(microsecond = 0) + is_game_data_outdated = saved_game.updated_last_on > obj_loaded_game.updated_last_on + + # Helper_App.console_log(f"loaded game updated last on: {obj_loaded_game.updated_last_on}") + # Helper_App.console_log(f"saved game updated last on: {saved_game.updated_last_on}") + # Helper_App.console_log(f"game oudated?: {is_game_data_outdated}") + return jsonify({ + Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_SUCCESS + , Model_View_MTG_Base.FLAG_DATA: is_game_data_outdated + }) + except Exception as e: + # Helper_App.console_log(f'{_m} Error: {str(e)}') + return jsonify({ + Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE + , Model_View_MTG_Base.FLAG_MESSAGE: f'Error: {str(e)}' + }), 500 + @routes_mtg_game.route('/mtg/api/game//players', methods=['GET']) def get_game_players(game_id): """Get players for a game with enriched user and deck information.""" _m = 'routes_mtg_game.get_game_players' - Helper_App.console_log(f'{_m}: game_id={game_id}') + # Helper_App.console_log(f'{_m}: game_id={game_id}') try: datastore = DataStore_MTG() user_session = datastore.get_user_session() @@ -182,7 +240,7 @@ def get_game_players(game_id): , Model_View_MTG_Base.FLAG_DATA: players_json }) except Exception as e: - Helper_App.console_log(f'{_m} Error: {str(e)}') + # Helper_App.console_log(f'{_m} Error: {str(e)}') return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error: {str(e)}' @@ -193,7 +251,7 @@ def get_game_players(game_id): def get_many_game_round(game_id): """Get rounds for a game.""" _m = 'routes_mtg_game.get_many_game_round' - Helper_App.console_log(f'{_m}: game_id={game_id}') + # Helper_App.console_log(f'{_m}: game_id={game_id}') try: datastore = DataStore_MTG() user_session = datastore.get_user_session() @@ -223,7 +281,7 @@ def get_many_game_round(game_id): , Model_View_MTG_Base.FLAG_DATA: rounds_json }) except Exception as e: - Helper_App.console_log(f'{_m} Error: {str(e)}') + # Helper_App.console_log(f'{_m} Error: {str(e)}') return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error: {str(e)}' @@ -234,7 +292,7 @@ def get_many_game_round(game_id): def get_many_game_player_damage(game_id): """Get damage records for a game.""" _m = 'routes_mtg_game.get_many_game_player_damage' - Helper_App.console_log(f'{_m}: game_id={game_id}') + # Helper_App.console_log(f'{_m}: game_id={game_id}') try: datastore = DataStore_MTG() user_session = datastore.get_user_session() @@ -263,7 +321,7 @@ def get_many_game_player_damage(game_id): , Model_View_MTG_Base.FLAG_DATA: damage_records }) except Exception as e: - Helper_App.console_log(f'{_m} Error: {str(e)}') + # Helper_App.console_log(f'{_m} Error: {str(e)}') return jsonify({ Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE , Model_View_MTG_Base.FLAG_MESSAGE: f'Error: {str(e)}' @@ -274,7 +332,7 @@ def get_many_game_player_damage(game_id): def save_game_player(): _m = 'routes_mtg_game.save_game_player' data = Helper_App.get_request_data(request) - Helper_App.console_log(f'{_m}\n{data}') + # Helper_App.console_log(f'{_m}\n{data}') try: """ form_filters = Filters_MTG_Game.from_json(data.get(Model_View_MTG_Base.FLAG_FORM_FILTERS, {})) @@ -301,7 +359,7 @@ def save_game_player(): objs_player = [] for player in players: obj_player = MTG_Game_Player.from_json(player) - Helper_App.console_log(f'obj_player = {obj_player}') + # Helper_App.console_log(f'obj_player = {obj_player}') objs_player.append(obj_player) success, errors = DataStore_MTG.save_mtg_game_player(objs_player) @@ -325,7 +383,7 @@ def save_game_player(): def save_game_round_player_damage(): _m = 'routes_mtg_game.save_game_round_player_damage' data = Helper_App.get_request_data(request) - Helper_App.console_log(f'{_m}\n{data}') + # Helper_App.console_log(f'{_m}\n{data}') try: datastore = DataStore_MTG() user_session = datastore.get_user_session() @@ -342,7 +400,7 @@ def save_game_round_player_damage(): objs_round = [] for round in rounds: obj_round = MTG_Game_Round.from_json(round) - Helper_App.console_log(f'obj_round = {obj_round}') + # Helper_App.console_log(f'obj_round = {obj_round}') objs_round.append(obj_round) damages = data.get(Model_View_MTG_Base.FLAG_DAMAGE, []) @@ -355,7 +413,7 @@ def save_game_round_player_damage(): objs_damage = [] for damage in damages: obj_damage = MTG_Game_Round_Player_Damage.from_json(damage) - Helper_App.console_log(f'obj_damage = {obj_damage}') + # Helper_App.console_log(f'obj_damage = {obj_damage}') objs_damage.append(obj_damage) success, errors = DataStore_MTG.save_mtg_game_round_player_damage(objs_round, objs_damage) @@ -379,14 +437,14 @@ def save_game_round_player_damage(): @routes_mtg_game.route(Model_View_MTG_Base.HASH_PAGE_MTG_DECKS, methods=['GET']) def decks(): - Helper_App.console_log('mtg decks') - Helper_App.console_log(f'request_args: {request.args}') + # Helper_App.console_log('mtg decks') + # Helper_App.console_log(f'request_args: {request.args}') try: form_filters = Filters_MTG_Deck.from_json(request.args) except Exception as e: - Helper_App.console_log(f'Error: {e}') + # Helper_App.console_log(f'Error: {e}') form_filters = Filters_MTG_Deck() - Helper_App.console_log(f'form_filters={form_filters}') + # Helper_App.console_log(f'form_filters={form_filters}') datastore = DataStore_MTG() user_session = datastore.get_user_session() @@ -397,6 +455,6 @@ def decks(): model = Model_View_MTG_Decks(parameters_deck = parameters_deck) model.form_filters = form_filters - Helper_App.console_log(f'form_filters={form_filters}') + # Helper_App.console_log(f'form_filters={form_filters}') return render_template('pages/tcg/mtg/_decks.html', model=model) diff --git a/controllers/user/user.py b/controllers/user/user.py index d21c25d..cbed57a 100644 --- a/controllers/user/user.py +++ b/controllers/user/user.py @@ -82,20 +82,22 @@ def login(): , state = quote(hash_callback) ) except Exception as e: - Helper_App.console_log(f"Error: {str(e)}") + Helper_App.console_log(f"Login error: {str(e)}") # Helper_App.console_log(f'redirect: {red}') headers = red.headers['Location'] # Helper_App.console_log(f'headers: {headers}') parsed_url = urlparse(headers) query_params = parse_qs(parsed_url.query) - Helper_App.console_log(f""" + """ + Helper_App.console_log(f"" " OAuth Authorize Redirect URL: Base URL: {parsed_url.scheme}://{parsed_url.netloc}{parsed_url.path} {parsed_url} Query Parameters: {query_params} - """) + "" ") + """ return jsonify({'Success': True, Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_SUCCESS, f'{Model_View_Base.FLAG_CALLBACK}': headers}) except Exception as e: @@ -113,17 +115,17 @@ def login_callback(): try: token = oauth.auth0.authorize_access_token() except Exception as e: - Helper_App.console_log(f"Error: {str(e)}") + Helper_App.console_log(f"Login callback token error: {str(e)}") session[current_app.config['ID_TOKEN_USER']] = token try: hash_callback = token.get('hash_callback') if hash_callback is None: - Helper_App.console_log('hash is none') + # Helper_App.console_log('hash is none') state = request.args.get('state') - Helper_App.console_log(f'state: {state}') + # Helper_App.console_log(f'state: {state}') hash_callback = state - Helper_App.console_log(f'hash_callback: {hash_callback}') + # Helper_App.console_log(f'hash_callback: {hash_callback}') except: Helper_App.console_log("get hash callback failed") @@ -136,7 +138,7 @@ def login_callback(): return redirect(f"{current_app.config['URL_HOST']}{hash_callback}") # login() user = User.from_json_auth0(token) - Helper_App.console_log(f'user: {user}') + # Helper_App.console_log(f'User from Auth0 json: {user}') """ session[Model_View_Base.FLAG_USER] = user.to_json() Helper_App.console_log(f'user stored on session') @@ -146,18 +148,19 @@ def login_callback(): try: saved_user, errors = datastore_user.login_user(user) if (len(errors) > 0): raise ValueError(f'Database errors: {errors}') - Helper_App.console_log('User logged in') - Helper_App.console_log(f'user ({str(type(saved_user))}): {saved_user}') - Helper_App.console_log(f'user key: {Model_View_Base.FLAG_USER}') + if (saved_user is None): raise ValueError(f'Not found.') + # Helper_App.console_log('User logged in') + # Helper_App.console_log(f'user ({str(type(saved_user))}): {saved_user}') + # Helper_App.console_log(f'user key: {Model_View_Base.FLAG_USER}') saved_user_json = saved_user.to_json() - Helper_App.console_log(f'User JSON: {saved_user_json}') + # Helper_App.console_log(f'Saved user JSON: {saved_user_json}') session[Model_View_Base.FLAG_USER] = saved_user_json - Helper_App.console_log(f'user stored on session') + # Helper_App.console_log(f'user stored on session') except Exception as e: Helper_App.console_log(f'User not found: {saved_user}\nDatabase query error: {errors}') - Helper_App.console_log(f'user session: {session.get(Model_View_Base.FLAG_USER, "(Key not found)")}') + # Helper_App.console_log(f'user session: {session.get(Model_View_Base.FLAG_USER, "(Key not found)")}') return redirect(f"{current_app.config['URL_HOST']}{hash_callback}") except Exception as e: return jsonify({Model_View_Base.FLAG_STATUS: Model_View_Base.FLAG_FAILURE, Model_View_Base.FLAG_MESSAGE: f'Controller error.\n{e}'}) @@ -171,7 +174,7 @@ def logout(): "client_id": current_app.config['ID_AUTH0_CLIENT'], } ) - Helper_App.console_log(f"Redirecting to {url_logout}") + # Helper_App.console_log(f"Redirecting to {url_logout}") return redirect(url_logout) @routes_user.route("/logout_callback") @@ -197,14 +200,14 @@ def user(): @routes_user.route(Model_View_User.HASH_PAGE_USER_ACCOUNTS) def users(): try: - Helper_App.console_log(f'request_args: {request.args}') + # Helper_App.console_log(f'request_args: {request.args}') user_session = Model_View_User.get_user_session() if (not user_session.get_is_logged_in()) or (not user_session.can_admin_user): return redirect(url_for('routes_mtg_game.home')) try: form_filters = Filters_User.from_json(request.args) except Exception as e: - Helper_App.console_log(f'Error: {e}') + # Helper_App.console_log(f'Error: {e}') form_filters = Filters_User.get_default() model = Model_View_User(form_filters, hash_page_current = Model_View_User.HASH_PAGE_USER_ACCOUNTS) html_body = render_template('pages/user/_users.html', model = model) @@ -236,7 +239,7 @@ def save_user(): objs_user = [] for user in users: objs_user.append(User.from_json(user)) - Helper_App.console_log(f'objs_user={objs_user}') + # Helper_App.console_log(f'objs_user={objs_user}') errors = DataStore_User.save_users(data.get('comment', 'No comment'), objs_user) if (len(errors) > 0): diff --git a/datastores/datastore_base.py b/datastores/datastore_base.py index d82ba35..874c135 100644 --- a/datastores/datastore_base.py +++ b/datastores/datastore_base.py @@ -59,7 +59,7 @@ class DataStore_Base(BaseModel): proc_string += f'{"" if i == 0 else ", "}{param_name} := {param_expr}' proc_string += ')' stmt = text(proc_string) - Helper_App.console_log(f'{_m}\nproc_string: {stmt}\nargs: {argument_dict_list}') + # Helper_App.console_log(f'{_m}\nproc_string: {stmt}\nargs: {argument_dict_list}') rows = [] with db.engine.connect().execution_options(isolation_level="AUTOCOMMIT") as conn: @@ -70,7 +70,7 @@ class DataStore_Base(BaseModel): # Fetch all rows as mappings before connection closes if result.returns_rows: rows = result.mappings().fetchall() - Helper_App.console_log(f'result: {rows}') + # Helper_App.console_log(f'result: {rows}') return rows # Map SQLAlchemy types to PostgreSQL type names for CAST() @@ -108,49 +108,49 @@ class DataStore_Base(BaseModel): func_string += ')' stmt = text(func_string) - Helper_App.console_log(f'{_m}\nfunc_string: {stmt}\nargs: {argument_dict_list}') + # Helper_App.console_log(f'{_m}\nfunc_string: {stmt}\nargs: {argument_dict_list}') if has_arguments: result = db.session.execute(stmt, argument_dict_list) else: result = db.session.execute(stmt) - Helper_App.console_log(f'result: {result}') + # Helper_App.console_log(f'result: {result}') return result @staticmethod def db_cursor_clear(cursor): while cursor.nextset(): - Helper_App.console_log(f'unexpected result set: {cursor.fetchall()}') + Helper_App.console_log(f'db_cursor_clear\nunexpected result set: {cursor.fetchall()}') @staticmethod def get_user_session(): - Helper_App.console_log('DataStore_Base.get_user_session') + # Helper_App.console_log('DataStore_Base.get_user_session') user = User.from_json(session.get(User.FLAG_USER)) """ if user.user_id <= 0: user.user_id = 3 """ - Helper_App.console_log(f'User: {user}') + # Helper_App.console_log(f'User: {user}') return user @staticmethod def upload_bulk(permanent_table_name, records, batch_size): _m = 'DataStore_Base.upload_bulk' - Helper_App.console_log(f'{_m}\nstarting...') - Helper_App.console_log(f'permanent_table_name: {permanent_table_name}') + # Helper_App.console_log(f'{_m}\nstarting...') + # Helper_App.console_log(f'permanent_table_name: {permanent_table_name}') if db.session.dirty or db.session.new or db.session.deleted: - Helper_App.console_log("Session is not clean") + # Helper_App.console_log("Session is not clean") return # Assuming `permanent_table_name` is a string representing the table name table_object = db.metadata.tables.get(permanent_table_name) - Helper_App.console_log(f'Tables: {list(db.metadata.tables.keys())}') + # Helper_App.console_log(f'Tables: {list(db.metadata.tables.keys())}') if table_object is None: - Helper_App.console_log(f"Table {permanent_table_name} not found in metadata.") + # Helper_App.console_log(f"Table {permanent_table_name} not found in metadata.") return - else: - expected_columns = set(column.name for column in db.inspect(table_object).columns) - Helper_App.console_log(f'table name: {table_object.name}') - Helper_App.console_log(f'expected_columns: {expected_columns}') + # else: + # expected_columns = set(column.name for column in db.inspect(table_object).columns) + # Helper_App.console_log(f'table name: {table_object.name}') + # Helper_App.console_log(f'expected_columns: {expected_columns}') max_retries = 3 initial_backoff = 1 for i in range(0, len(records), batch_size): @@ -180,7 +180,7 @@ class DataStore_Base(BaseModel): except Exception as e: db.session.rollback() raise e - Helper_App.console_log(f'Records uploaded in batches.') + # Helper_App.console_log(f'Records uploaded in batches.') @classmethod def get_many_error(cls, guid): @@ -189,23 +189,23 @@ class DataStore_Base(BaseModel): arguments = Parameters_SQL_Error.get_default(guid) argument_dict = arguments.to_json() argument_types = Parameters_SQL_Error.get_type_hints() - Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') + # Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') errors = [] try: error_result = cls.db_function_execute('tcg.public.FN_Error_Get_Many', argument_dict, argument_types) error_result_set = error_result.fetchall() - Helper_App.console_log(f'raw errors: {error_result_set}') + # Helper_App.console_log(f'raw errors: {error_result_set}') errors = [] error_indexes = {} for row in error_result_set: new_error = SQL_Error.from_db_error(row) error_indexes[new_error.error_id] = len(errors) errors.append(new_error) - Helper_App.console_log(f'error {str(type(new_error))}: {new_error}') + # Helper_App.console_log(f'error {str(type(new_error))}: {new_error}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -219,7 +219,7 @@ class DataStore_Base(BaseModel): arguments = Parameters_SQL_Error.get_default(guid) argument_dict = arguments.to_json() argument_types = Parameters_SQL_Error.get_type_hints() - Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') + # Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') cls.db_procedure_execute('tcg.public.USP_Error_Clear', argument_dict, argument_types) diff --git a/datastores/datastore_mtg.py b/datastores/datastore_mtg.py index 95428a8..1d888db 100644 --- a/datastores/datastore_mtg.py +++ b/datastores/datastore_mtg.py @@ -18,6 +18,7 @@ from business_objects.tcg.mtg_game import MTG_Game, Parameters_MTG_Game from business_objects.tcg.mtg_game_player import MTG_Game_Player, Parameters_MTG_Game_Player, MTG_Game_Player_Temp from business_objects.tcg.mtg_game_round import MTG_Game_Round, Parameters_MTG_Game_Round, MTG_Game_Round_Temp from business_objects.tcg.mtg_game_round_player_damage import MTG_Game_Round_Player_Damage, Parameters_MTG_Game_Round_Player_Damage, MTG_Game_Round_Player_Damage_Temp +from business_objects.tcg.mtg_game_session_member import MTG_Game_Session_Member, Parameters_MTG_Game_Session_Member from business_objects.tcg.statistic import Statistic, Statistic_Temp, Parameters_Statistic from business_objects.sql_error import SQL_Error, Parameters_SQL_Error from datastores.datastore_base import DataStore_Base @@ -45,23 +46,23 @@ class DataStore_MTG(DataStore_Base): # user = cls.get_user_session() argument_dict = game_filters.to_json() argument_types = Parameters_MTG_Game.get_type_hints() - Helper_App.console_log(f'argument_dict: {argument_dict}') + # Helper_App.console_log(f'argument_dict: {argument_dict}') games = [] errors = [] try: game_result = cls.db_function_execute('tcg.public.FN_TCG_MTG_Game_Get_Many', argument_dict, argument_types) game_result_set = game_result.fetchall() - Helper_App.console_log(f'raw games: {game_result_set}') + # Helper_App.console_log(f'raw games: {game_result_set}') games = [] game_indexes = {} for row in game_result_set: new_game = MTG_Game.from_db_mtg_game(row) game_indexes[new_game.game_id] = len(games) games.append(new_game) - Helper_App.console_log(f'game {str(type(new_game))}: {new_game}') + # Helper_App.console_log(f'game {str(type(new_game))}: {new_game}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -109,7 +110,7 @@ class DataStore_MTG(DataStore_Base): , 'o_game_id': Integer , 'o_success': Boolean } - Helper_App.console_log(f'argument_dict: {argument_dict}') + # Helper_App.console_log(f'argument_dict: {argument_dict}') errors = [] try: @@ -117,12 +118,12 @@ class DataStore_MTG(DataStore_Base): row = rows[0] if rows else None game_id = row['o_game_id'] if row else None success = row['o_success'] if row else False - Helper_App.console_log(f'Game ID: {game_id}') - Helper_App.console_log(f'Success: {success}') + # Helper_App.console_log(f'Game ID: {game_id}') + # Helper_App.console_log(f'Success: {success}') if not success: errors = cls.get_many_error(guid = guid) except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -136,20 +137,20 @@ class DataStore_MTG(DataStore_Base): _m = f'{cls.__qualname__}.get_many_mtg_game_player' argument_dict = player_filters.to_json() argument_types = Parameters_MTG_Game_Player.get_type_hints() - Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') + # Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') players = [] errors = [] try: result = cls.db_function_execute('tcg.public.FN_TCG_MTG_Game_Player_Get_Many', argument_dict, argument_types) result_set = result.fetchall() - Helper_App.console_log(f'raw players: {result_set}') + # Helper_App.console_log(f'raw players: {result_set}') for row in result_set: new_player = MTG_Game_Player.from_db_mtg_game_player(row) players.append(new_player) - Helper_App.console_log(f'player {str(type(new_player))}: {new_player}') + # Helper_App.console_log(f'player {str(type(new_player))}: {new_player}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -161,20 +162,20 @@ class DataStore_MTG(DataStore_Base): _m = f'{cls.__qualname__}.get_many_mtg_game_round' argument_dict = round_filters.to_json() argument_types = Parameters_MTG_Game_Round.get_type_hints() - Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') + # Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') rounds = [] errors = [] try: result = cls.db_function_execute('tcg.public.FN_TCG_MTG_Game_Round_Get_Many', argument_dict, argument_types) result_set = result.fetchall() - Helper_App.console_log(f'raw rounds: {result_set}') + # Helper_App.console_log(f'raw rounds: {result_set}') for row in result_set: new_round = MTG_Game_Round.from_db_mtg_game_round(row) rounds.append(new_round) - Helper_App.console_log(f'round {str(type(new_round))}: {new_round}') + # Helper_App.console_log(f'round {str(type(new_round))}: {new_round}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -186,20 +187,20 @@ class DataStore_MTG(DataStore_Base): _m = f'{cls.__qualname__}.get_many_mtg_game_round_player_damage' argument_dict = damage_filters.to_json() argument_types = Parameters_MTG_Game_Round_Player_Damage.get_type_hints() - Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') + # Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') damages = [] errors = [] try: result = cls.db_function_execute('tcg.public.FN_TCG_MTG_Game_Round_Player_Damage_Get_Many', argument_dict, argument_types) result_set = result.fetchall() - Helper_App.console_log(f'raw damages: {result_set}') + # Helper_App.console_log(f'raw damages: {result_set}') for row in result_set: new_damage = MTG_Game_Round_Player_Damage.from_db_mtg_game_round_player_damage(row) damages.append(new_damage) - Helper_App.console_log(f'damage {str(type(new_damage))}: {new_damage.damage_id}') + # Helper_App.console_log(f'damage {str(type(new_damage))}: {new_damage.damage_id}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -211,20 +212,20 @@ class DataStore_MTG(DataStore_Base): _m = f'{cls.__qualname__}.get_many_mtg_deck' argument_dict = deck_filters.to_json() argument_types = Parameters_MTG_Deck.get_type_hints() - Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') + # Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') decks = [] errors = [] try: result = cls.db_function_execute('tcg.public.FN_TCG_MTG_Deck_Get_Many', argument_dict, argument_types) result_set = result.fetchall() - Helper_App.console_log(f'raw decks: {result_set}') + # Helper_App.console_log(f'raw decks: {result_set}') for row in result_set: new_deck = MTG_Deck.from_db_mtg_deck(row) decks.append(new_deck) - Helper_App.console_log(f'deck {str(type(new_deck))}: {new_deck}') + # Helper_App.console_log(f'deck {str(type(new_deck))}: {new_deck}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -250,7 +251,7 @@ class DataStore_MTG(DataStore_Base): , 'a_user_id': Integer , 'o_success': Boolean } - Helper_App.console_log(f'argument_dict: {argument_dict}') + # Helper_App.console_log(f'argument_dict: {argument_dict}') objs_player_temp = [] for player in players: @@ -268,12 +269,12 @@ class DataStore_MTG(DataStore_Base): rows = cls.db_procedure_execute('tcg.public.USP_TCG_MTG_Game_Player_Save', argument_dict, argument_type_hints) row = rows[0] if rows else None success = row['o_success'] if row else False - Helper_App.console_log(f'Success: {success}') + # Helper_App.console_log(f'Success: {success}') if not success: errors = cls.get_many_error(guid = guid) - Helper_App.console_log(f'Errors: {str(errors)}') + # Helper_App.console_log(f'Errors: {str(errors)}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -300,7 +301,7 @@ class DataStore_MTG(DataStore_Base): , 'a_user_id': Integer , 'o_success': Boolean } - Helper_App.console_log(f'argument_dict: {argument_dict}') + # Helper_App.console_log(f'argument_dict: {argument_dict}') objs_round_temp = [] for round in rounds: @@ -328,12 +329,12 @@ class DataStore_MTG(DataStore_Base): rows = cls.db_procedure_execute('tcg.public.USP_TCG_MTG_Game_Round_Damage_Save', argument_dict, argument_type_hints) row = rows[0] if rows else None success = row['o_success'] if row else False - Helper_App.console_log(f'Success: {success}') + # Helper_App.console_log(f'Success: {success}') if not success: errors = cls.get_many_error(guid = guid) - Helper_App.console_log(f'Errors: {str(errors)}') + # Helper_App.console_log(f'Errors: {str(errors)}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -348,20 +349,20 @@ class DataStore_MTG(DataStore_Base): _m = f'{cls.__qualname__}.get_many_mtg_deck_commander_bracket' argument_dict = parameters_commander_bracket.to_json() argument_types = Parameters_MTG_Deck.get_type_hints() - Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') + # Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') commander_brackets = [] errors = [] try: result = cls.db_function_execute('tcg.public.FN_TCG_MTG_Deck_Commander_Bracket_Get_Many', argument_dict, argument_types) result_set = result.fetchall() - Helper_App.console_log(f'raw commander brackets: {result_set}') + # Helper_App.console_log(f'raw commander brackets: {result_set}') for row in result_set: new_commander_bracket = MTG_Deck_Commander_Bracket.from_db_mtg_deck_commander_bracket(row) commander_brackets.append(new_commander_bracket) - Helper_App.console_log(f'commander bracket {str(type(new_commander_bracket))}: {new_commander_bracket}') + # Helper_App.console_log(f'commander bracket {str(type(new_commander_bracket))}: {new_commander_bracket}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) @@ -374,22 +375,44 @@ class DataStore_MTG(DataStore_Base): _m = f'{cls.__qualname__}.get_many_statistic' argument_dict = parameters_statistic.to_json() argument_types = Parameters_MTG_Deck.get_type_hints() - Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') + # Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}') statistics = [] errors = [] try: result = cls.db_function_execute('tcg.public.FN_TCG_Statistic_Get_Many', argument_dict, argument_types) result_set = result.fetchall() - Helper_App.console_log(f'raw commander brackets: {result_set}') + # Helper_App.console_log(f'raw commander brackets: {result_set}') for row in result_set: new_statistic = Statistic.from_db_statistic(row) statistics.append(new_statistic) - Helper_App.console_log(f'statistic {str(type(new_statistic))}: {new_statistic}') + # Helper_App.console_log(f'statistic {str(type(new_statistic))}: {new_statistic}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) - return statistics, errors + return statistics, + + @classmethod + def get_many_mtg_game_session_member(cls, member_filters): + argument_dict = member_filters.to_json() + argument_types = Parameters_MTG_Game_Session_Member.get_type_hints() + + members = [] + errors = [] + try: + result = cls.db_function_execute('tcg.public.FN_TCG_MTG_Game_Session_Member_Get_Many', argument_dict, argument_types) + result_set = result.fetchall() + for row in result_set: + new_member = MTG_Game_Session_Member.from_db_mtg_game_player(row) + members.append(new_member) + except Exception as e: + error = SQL_Error() + error.msg = str(e) + errors.append(error) + + return members, errors + + diff --git a/datastores/datastore_user.py b/datastores/datastore_user.py index 2fd6a3c..3124777 100644 --- a/datastores/datastore_user.py +++ b/datastores/datastore_user.py @@ -15,6 +15,7 @@ Datastore for Users import lib.argument_validation as av from business_objects.sql_error import SQL_Error from business_objects.tcg.user import User, Parameters_User +from business_objects.tcg.user_relationship import User_Relationship, Parameters_User_Relationship from datastores.datastore_base import DataStore_Base from helpers.helper_app import Helper_App from helpers.helper_db_sql import Helper_DB_SQL @@ -41,33 +42,55 @@ class DataStore_User(DataStore_Base): @classmethod def get_many_user(cls, user_filters): _m = f'{cls.__qualname__}.get_many_user' - Helper_App.console_log(_m) - Helper_App.console_log(f'user_filters: {user_filters}') + # Helper_App.console_log(_m) + # Helper_App.console_log(f'user_filters: {user_filters}') av.val_instance(user_filters, 'user_filters', _m, Parameters_User) argument_dict = user_filters.to_json() - Helper_App.console_log(f'argument_dict: {argument_dict}') + # Helper_App.console_log(f'argument_dict: {argument_dict}') users = [] errors = [] try: user_result = cls.db_function_execute('tcg.public.FN_TCG_User_Get_Many', argument_dict, Parameters_User.get_type_hints()) user_result_set = user_result.fetchall() - Helper_App.console_log(f'raw users: {user_result_set}') + # Helper_App.console_log(f'raw users: {user_result_set}') for row in user_result_set: - Helper_App.console_log(f'row: {row}') + # Helper_App.console_log(f'row: {row}') user = User.from_db_user(row) users.append(user) - Helper_App.console_log(f'user {str(type(user))}: {user}') + # Helper_App.console_log(f'user {str(type(user))}: {user}') except Exception as e: - Helper_App.console_log(f'Error: {str(e)}') + # Helper_App.console_log(f'Error: {str(e)}') error = SQL_Error() error.msg = str(e) errors.append(error) return users, errors + @classmethod + def get_many_user_relationship(cls, relationship_filters): + _m = f'{cls.__qualname__}.get_many_user_relationship' + av.val_instance(relationship_filters, 'relationship_filters', _m, Parameters_User_Relationship) + + argument_dict = relationship_filters.to_json() + + relationships = [] + errors = [] + try: + result = cls.db_function_execute('tcg.public.FN_TCG_User_Relationship_Get_Many', argument_dict, Parameters_User_Relationship.get_type_hints()) + result_set = result.fetchall() + for row in result_set: + relationship = User_Relationship.from_db_user_relationship(row) + relationships.append(relationship) + except Exception as e: + error = SQL_Error() + error.msg = str(e) + errors.append(error) + + return relationships, errors + @classmethod def login_user(cls, user): _m = f'{cls}.login_user' @@ -75,7 +98,7 @@ class DataStore_User(DataStore_Base): guid = Helper_DB_SQL.create_guid_str() - Helper_App.console_log(f'login user: {user}') + # Helper_App.console_log(f'login user: {user}') success = False user_id = None @@ -92,8 +115,8 @@ class DataStore_User(DataStore_Base): row = rows[0] if rows else None success = row['o_success'] if row else False user_id = row['o_user_id'] if row else None - Helper_App.console_log('User logged in') - Helper_App.console_log(f'Success: {success}\nUser ID: {user_id}') + # Helper_App.console_log('User logged in') + # Helper_App.console_log(f'Success: {success}\nUser ID: {user_id}') user.user_id = user_id user_filters = Parameters_User.from_user(user) diff --git a/forms/tcg/game.py b/forms/tcg/game.py index 3a0fe46..5497734 100644 --- a/forms/tcg/game.py +++ b/forms/tcg/game.py @@ -63,7 +63,7 @@ class Filters_MTG_Game(Form_Base): @classmethod def from_json(cls, json): _m = f'{cls.__qualname__}.from_json' - Helper_App.console_log(f'{_m}\njson: {json}') + # Helper_App.console_log(f'{_m}\njson: {json}') filters = cls() filters.search.data = json.get(Base.FLAG_SEARCH, '') filters.active_only.data = av.input_bool(json.get(Base.FLAG_ACTIVE_ONLY, True), Base.FLAG_ACTIVE_ONLY, _m) @@ -112,7 +112,7 @@ class Filters_MTG_Game_Player(Form_Base): @classmethod def from_json(cls, json): _m = f'{cls.__qualname__}.from_json' - Helper_App.console_log(f'{_m}\njson: {json}') + # Helper_App.console_log(f'{_m}\njson: {json}') filters = cls() filters.search.data = json.get(Base.FLAG_SEARCH, '') filters.active_only.data = av.input_bool(json.get(Base.FLAG_ACTIVE_ONLY, True), Base.FLAG_ACTIVE_ONLY, _m) @@ -156,7 +156,7 @@ class Filters_MTG_Deck(Form_Base): @classmethod def from_json(cls, json): _m = f'{cls.__qualname__}.from_json' - Helper_App.console_log(f'{_m}\njson: {json}') + # Helper_App.console_log(f'{_m}\njson: {json}') filters = cls() filters.search.data = json.get(Base.FLAG_SEARCH, '') filters.active_only.data = av.input_bool(json.get(Base.FLAG_ACTIVE_ONLY, True), Base.FLAG_ACTIVE_ONLY, _m) diff --git a/forms/tcg/user.py b/forms/tcg/user.py index 78ecbdc..3dbe4ed 100644 --- a/forms/tcg/user.py +++ b/forms/tcg/user.py @@ -41,7 +41,7 @@ class Filters_User(Form_Base): @classmethod def from_json(cls, json): _m = f'{cls.__qualname__}.from_json' - Helper_App.console_log(f'{_m}\njson: {json}') + # Helper_App.console_log(f'{_m}\njson: {json}') filters = cls() filters.search.data = json[Base.FLAG_SEARCH] filters.active_only.data = av.input_bool(json[Base.FLAG_ACTIVE_ONLY], Base.FLAG_ACTIVE_ONLY, f'{cls.__name__}.from_json') diff --git a/helpers/helper_app.py b/helpers/helper_app.py index 793812c..ef706ff 100644 --- a/helpers/helper_app.py +++ b/helpers/helper_app.py @@ -19,7 +19,7 @@ class Helper_App(BaseModel): @staticmethod def get_request_data(request): - Helper_App.console_log(f'request={request}') + # Helper_App.console_log(f'request={request}') data = {} try: data = request.json @@ -31,7 +31,7 @@ class Helper_App(BaseModel): data = request.form except: pass - Helper_App.console_log(f'data={data}') + # Helper_App.console_log(f'data={data}') return data @staticmethod diff --git a/models/model_view_base.py b/models/model_view_base.py index 617ead6..27b5790 100644 --- a/models/model_view_base.py +++ b/models/model_view_base.py @@ -249,7 +249,7 @@ class Model_View_Base(BaseModel, ABC): self.app = current_app with self.app.app_context(): self.session = session - Helper_App.console_log(f'session: {self.session}') + # Helper_App.console_log(f'session: {self.session}') datastore_base = DataStore_Base() self.user = datastore_base.get_user_session() diff --git a/models/model_view_mtg_base.py b/models/model_view_mtg_base.py index 44f14ae..7964051 100644 --- a/models/model_view_mtg_base.py +++ b/models/model_view_mtg_base.py @@ -75,7 +75,7 @@ class Model_View_MTG_Base(Model_View_Base): def __init__(self, hash_page_current, **kwargs): _m = 'Model_View_MTG_Base.__init__' - Helper_App.console_log(f'{_m}\nstarting') + # Helper_App.console_log(f'{_m}\nstarting') super().__init__(hash_page_current=hash_page_current, **kwargs) self.is_page_mtg = True if self.hash_page_current == Model_View_MTG_Base.HASH_PAGE_MTG_TRIAL_GAME: diff --git a/models/model_view_mtg_decks.py b/models/model_view_mtg_decks.py index d3f6de8..3f14770 100644 --- a/models/model_view_mtg_decks.py +++ b/models/model_view_mtg_decks.py @@ -34,21 +34,16 @@ class Model_View_MTG_Decks(Model_View_MTG_Base): def __init__(self, parameters_deck=None, hash_page_current=Model_View_MTG_Base.HASH_PAGE_MTG_DECKS): _m = 'Model_View_MTG_Decks.__init__' - Helper_App.console_log(f'{_m}\nstarting...') + # Helper_App.console_log(f'{_m}\nstarting...') super().__init__(hash_page_current=hash_page_current) self._title = 'MTG Decks' datastore = DataStore_MTG() # Get all decks - parameters_deck = Parameters_MTG_Deck.get_default() - parameters_deck.get_all_deck = True - parameters_deck.require_all_id_filters_met = False - parameters_deck.require_any_id_filters_met = False - parameters_deck.require_all_non_id_filters_met = False - parameters_deck.require_any_non_id_filters_met = False + parameters_deck = Parameters_MTG_Deck.get_default(self.user.user_id) self.decks, errors = datastore.get_many_mtg_deck(parameters_deck) - Helper_App.console_log(f'Decks IDs: {self.decks}') + # Helper_App.console_log(f'Decks IDs: {self.decks}') # Get all commander brackets parameters_commander_bracket = Parameters_MTG_Deck_Commander_Bracket.get_default() parameters_commander_bracket.get_all_commander_bracket = True @@ -56,12 +51,12 @@ class Model_View_MTG_Decks(Model_View_MTG_Base): parameters_commander_bracket.require_any_id_filters_met = False self.commander_brackets, errors = datastore.get_many_mtg_deck_commander_bracket(parameters_commander_bracket = parameters_commander_bracket) - Helper_App.console_log(f'Brackets: {self.commander_brackets}') + # Helper_App.console_log(f'Brackets: {self.commander_brackets}') commander_bracket_index = {} for index_commander_bracket in range(len(self.commander_brackets)): bracket = self.commander_brackets[index_commander_bracket] commander_bracket_index[bracket.commander_bracket_id] = bracket - Helper_App.console_log(f'Bracket IDs: {commander_bracket_index}') + # Helper_App.console_log(f'Bracket IDs: {commander_bracket_index}') deck_index = {} for index_deck in range(len(self.decks)): diff --git a/models/model_view_mtg_game.py b/models/model_view_mtg_game.py index d7f2a38..03e449a 100644 --- a/models/model_view_mtg_game.py +++ b/models/model_view_mtg_game.py @@ -36,6 +36,8 @@ class Model_View_MTG_Game(Model_View_MTG_Base): FLAG_ROUND_DISPLAY_ORDER_BUTTON: ClassVar[str] = 'btn-round-display-order' FLAG_ROUND_DISPLAY_ORDER_MINUS: ClassVar[str] = 'round-display-order-minus' FLAG_ROUND_DISPLAY_ORDER_PLUS: ClassVar[str] = 'round-display-order-plus' + GAME_DATA_OUTDATED_LABEL_ID: ClassVar[str] = 'game-data-outdated-label' + ID_OVERLAY_GAME_OUTDATED: ClassVar[str] = 'overlay-game-outdated' PLAYER_SETUP_WRAPPER_TEMPLATE_ID: ClassVar[str] = 'player-setup-wrapper-template' damage_records: list = None @@ -53,7 +55,7 @@ class Model_View_MTG_Game(Model_View_MTG_Base): def __init__(self, game_id, hash_page_current=Model_View_MTG_Base.HASH_PAGE_MTG_GAME): _m = 'Model_View_MTG_Game.__init__' - Helper_App.console_log(f'{_m}\nstarting...') + # Helper_App.console_log(f'{_m}\nstarting...') super().__init__(hash_page_current=hash_page_current) self._title = 'MTG Game' datastore = DataStore_MTG() @@ -68,7 +70,7 @@ class Model_View_MTG_Game(Model_View_MTG_Base): self.game = games[0] # Get all decks - parameters_deck = Parameters_MTG_Deck.get_default() + parameters_deck = Parameters_MTG_Deck.get_default(user_session.user_id) parameters_deck.get_all_deck = True parameters_deck.require_all_id_filters_met = False parameters_deck.require_any_id_filters_met = False diff --git a/models/model_view_mtg_games.py b/models/model_view_mtg_games.py index 4ab5f52..eb49b3a 100644 --- a/models/model_view_mtg_games.py +++ b/models/model_view_mtg_games.py @@ -29,7 +29,7 @@ class Model_View_MTG_Games(Model_View_MTG_Base): def __init__(self, parameters_game=None, hash_page_current=Model_View_MTG_Base.HASH_PAGE_MTG_GAMES): _m = 'Model_View_MTG_Games.__init__' - Helper_App.console_log(f'{_m}\nstarting...') + # Helper_App.console_log(f'{_m}\nstarting...') super().__init__(hash_page_current=hash_page_current) self._title = 'MTG Games' datastore = DataStore_MTG() @@ -41,5 +41,5 @@ class Model_View_MTG_Games(Model_View_MTG_Base): else: self.parameters_game = parameters_game - Helper_App.console_log(f'Query args: {self.parameters_game}') + # Helper_App.console_log(f'Query args: {self.parameters_game}') self.games, errors = datastore.get_many_mtg_game(self.parameters_game) diff --git a/models/model_view_mtg_home.py b/models/model_view_mtg_home.py index a234576..b183207 100644 --- a/models/model_view_mtg_home.py +++ b/models/model_view_mtg_home.py @@ -27,6 +27,6 @@ class Model_View_MTG_Home(Model_View_MTG_Base): def __init__(self, hash_page_current=Model_View_MTG_Base.HASH_PAGE_MTG_HOME): _m = 'Model_View_MTG_Home.__init__' - Helper_App.console_log(f'{_m}\nstarting...') + # Helper_App.console_log(f'{_m}\nstarting...') super().__init__(hash_page_current=hash_page_current) self._title = 'MTG Home' diff --git a/models/model_view_user.py b/models/model_view_user.py index 7ce2518..28f8903 100644 --- a/models/model_view_user.py +++ b/models/model_view_user.py @@ -37,13 +37,13 @@ class Model_View_User(Model_View_Base): self._title = 'Users' self.form_filters = form_filters_old - Helper_App.console_log(f'Form filters: {self.form_filters}') + # Helper_App.console_log(f'Form filters: {self.form_filters}') datastore = DataStore_User() parameters_user = Parameters_User.from_form_filters_user(self.form_filters) if self.hash_page_current == Model_View_Base.HASH_PAGE_USER_ACCOUNT: parameters_user.user_ids = str(self.user.user_id) - Helper_App.console_log(f'Query args: {parameters_user}') + # Helper_App.console_log(f'Query args: {parameters_user}') self.users, errors = datastore.get_many_user(parameters_user) \ No newline at end of file diff --git a/static/PostgreSQL/10508_tbl_TCG_User_Relationship.sql b/static/PostgreSQL/10508_tbl_TCG_User_Relationship.sql new file mode 100644 index 0000000..615eb1e --- /dev/null +++ b/static/PostgreSQL/10508_tbl_TCG_User_Relationship.sql @@ -0,0 +1,29 @@ + +CREATE TABLE tcg.public.TCG_User_Relationship ( + relationship_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY + , follower_user_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_follower_user_id + FOREIGN KEY (follower_user_id) + REFERENCES tcg.public.TCG_User(user_id) + , following_user_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_following_user_id + FOREIGN KEY (following_user_id) + REFERENCES tcg.public.TCG_User(user_id) + , is_following BOOLEAN NOT NULL DEFAULT TRUE + , is_blocked BOOLEAN NOT NULL DEFAULT FALSE + , active BOOLEAN NOT NULL DEFAULT TRUE + , created_on TIMESTAMP NOT NULL + , created_by_user_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_created_by_user_id + FOREIGN KEY (created_by_user_id) + REFERENCES tcg.public.TCG_User(user_id) + , updated_last_on TIMESTAMP NOT NULL + , updated_last_by_user_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_updated_last_by_user_id + FOREIGN KEY (updated_last_by_user_id) + REFERENCES tcg.public.TCG_User(user_id) + , change_set_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_change_set_id + FOREIGN KEY (change_set_id) + REFERENCES tcg.public.TCG_Change_Set(change_set_id) +); diff --git a/static/PostgreSQL/10509_tbl_TCG_User_Relationship_Audit.sql b/static/PostgreSQL/10509_tbl_TCG_User_Relationship_Audit.sql new file mode 100644 index 0000000..0e291f9 --- /dev/null +++ b/static/PostgreSQL/10509_tbl_TCG_User_Relationship_Audit.sql @@ -0,0 +1,15 @@ + +CREATE TABLE tcg.public.TCG_User_Relationship_Audit ( + audit_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY + , relationship_id INT NOT NULL + , CONSTRAINT FK_TCG_User_Audit_relationship_id + FOREIGN KEY (relationship_id) + REFERENCES tcg.public.TCG_User_Relationship(relationship_id) + , name_field TEXT NOT NULL + , value_prev TEXT + , value_new TEXT + , change_set_id INT NOT NULL + , CONSTRAINT FK_TCG_User_Audit_change_set_id + FOREIGN KEY (change_set_id) + REFERENCES tcg.public.TCG_Change_Set(change_set_id) +); \ No newline at end of file diff --git a/static/PostgreSQL/10510_tbl_TCG_User_Relationship_Temp.sql b/static/PostgreSQL/10510_tbl_TCG_User_Relationship_Temp.sql new file mode 100644 index 0000000..a8c70d5 --- /dev/null +++ b/static/PostgreSQL/10510_tbl_TCG_User_Relationship_Temp.sql @@ -0,0 +1,17 @@ + +CREATE TABLE tcg.public.TCG_User_Relationship_Temp ( + temp_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY + , relationship_id INT + , follower_user_id INT + , following_user_id INT + , is_following BOOLEAN + , is_blocked BOOLEAN + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT + , change_set_id INT + + , guid UUID NOT NULL +); diff --git a/static/PostgreSQL/10510_tbl_Error_Type.sql b/static/PostgreSQL/10520_tbl_Error_Type.sql similarity index 100% rename from static/PostgreSQL/10510_tbl_Error_Type.sql rename to static/PostgreSQL/10520_tbl_Error_Type.sql diff --git a/static/PostgreSQL/10511_tbl_Error_Type_Audit.sql b/static/PostgreSQL/10521_tbl_Error_Type_Audit.sql similarity index 100% rename from static/PostgreSQL/10511_tbl_Error_Type_Audit.sql rename to static/PostgreSQL/10521_tbl_Error_Type_Audit.sql diff --git a/static/PostgreSQL/10514_tbl_Error.sql b/static/PostgreSQL/10524_tbl_Error.sql similarity index 100% rename from static/PostgreSQL/10514_tbl_Error.sql rename to static/PostgreSQL/10524_tbl_Error.sql diff --git a/static/PostgreSQL/10515_tbl_Error_Audit.sql b/static/PostgreSQL/10525_tbl_Error_Audit.sql similarity index 100% rename from static/PostgreSQL/10515_tbl_Error_Audit.sql rename to static/PostgreSQL/10525_tbl_Error_Audit.sql diff --git a/static/PostgreSQL/11152_tbl_TCG_MTG_Inventory_Temp.sql b/static/PostgreSQL/11152_tbl_TCG_MTG_Inventory_Temp.sql index 57c16c4..780ab69 100644 --- a/static/PostgreSQL/11152_tbl_TCG_MTG_Inventory_Temp.sql +++ b/static/PostgreSQL/11152_tbl_TCG_MTG_Inventory_Temp.sql @@ -3,17 +3,8 @@ CREATE TABLE tcg.public.TCG_MTG_Inventory_Temp ( temp_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY , inventory_id INT , card_id INT - , CONSTRAINT FK_TCG_MTG_Inventory_Temp_card_id - FOREIGN KEY (card_id) - REFERENCES tcg.public.TCG_MTG_Card(card_id) , finish_id INT NOT NULL - , CONSTRAINT FK_TCG_MTG_Inventory_Temp_finish_id - FOREIGN KEY (finish_id) - REFERENCES tcg.public.TCG_MTG_Finish(finish_id) , condition_id INT NOT NULL - , CONSTRAINT FK_TCG_MTG_Inventory_Temp_condition_id - FOREIGN KEY (condition_id) - REFERENCES tcg.public.TCG_Condition(condition_id) , sleeve_colour_name TEXT , location_name TEXT , acquired_from TEXT @@ -31,40 +22,22 @@ CREATE TABLE tcg.public.TCG_MTG_Inventory_Temp ( , miscut_errors TEXT , playability TEXT , owner_user_id INT NOT NULL - , CONSTRAINT FK_TCG_MTG_Inventory_Temp_owner_user_id - FOREIGN KEY (owner_user_id) - REFERENCES tcg.public.TCG_User(user_id) , ownership_status_name TEXT , trading_status_name TEXT , loaned_to_user_id INT - , CONSTRAINT FK_TCG_MTG_Inventory_Temp_loaned_to_user_id - FOREIGN KEY (loaned_to_user_id) - REFERENCES tcg.public.TCG_User(user_id) , loan_start_on TIMESTAMP , loan_end_on TIMESTAMP , provenance TEXT , signed_by_names TEXT , signature_condition_name TEXT , token_rear_side_card_id INT - , CONSTRAINT FK_TCG_MTG_Inventory_token_rear_side_card_id - FOREIGN KEY (token_rear_side_card_id) - REFERENCES tcg.public.TCG_MTG_Card(card_id) , display_order INT NOT NULL , active BOOLEAN NOT NULL DEFAULT TRUE -- , created_on TIMESTAMP NOT NULL , created_by_user_id INT NOT NULL - , CONSTRAINT FK_TCG_MTG_Inventory_Temp_created_by_user_id - FOREIGN KEY (created_by_user_id) - REFERENCES tcg.public.TCG_User(user_id) -- , updated_last_on TIMESTAMP NOT NULL , updated_last_by_user_id INT NOT NULL - , CONSTRAINT FK_TCG_MTG_Inventory_Temp_updated_last_by_user_id - FOREIGN KEY (updated_last_by_user_id) - REFERENCES tcg.public.TCG_User(user_id) , change_set_id INT NOT NULL - , CONSTRAINT FK_TCG_MTG_Inventory_Temp_change_set_id - FOREIGN KEY (change_set_id) - REFERENCES tcg.public.TCG_Change_Set(change_set_id) , guid UUID NOT NULL , set_code TEXT diff --git a/static/PostgreSQL/11224_tbl_TCG_MTG_Game_Session_Member.sql b/static/PostgreSQL/11224_tbl_TCG_MTG_Game_Session_Member.sql new file mode 100644 index 0000000..52ead69 --- /dev/null +++ b/static/PostgreSQL/11224_tbl_TCG_MTG_Game_Session_Member.sql @@ -0,0 +1,28 @@ + +CREATE TABLE tcg.public.TCG_MTG_Game_Session_Member ( + member_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY + , game_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_game_id + FOREIGN KEY (game_id) + REFERENCES tcg.public.TCG_MTG_Game(game_id) + , user_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_user_id + FOREIGN KEY (user_id) + REFERENCES tcg.public.TCG_User(user_id) + , is_permitted BOOLEAN NOT NULL DEFAULT FALSE + , active BOOLEAN NOT NULL DEFAULT TRUE + , created_on TIMESTAMP NOT NULL + , created_by_user_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_created_by_user_id + FOREIGN KEY (created_by_user_id) + REFERENCES tcg.public.TCG_User(user_id) + , updated_last_on TIMESTAMP NOT NULL + , updated_last_by_user_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_updated_last_by_user_id + FOREIGN KEY (updated_last_by_user_id) + REFERENCES tcg.public.TCG_User(user_id) + , change_set_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_change_set_id + FOREIGN KEY (change_set_id) + REFERENCES tcg.public.TCG_Change_Set(change_set_id) +); diff --git a/static/PostgreSQL/11225_tbl_TCG_MTG_Game_Session_Member_Audit.sql b/static/PostgreSQL/11225_tbl_TCG_MTG_Game_Session_Member_Audit.sql new file mode 100644 index 0000000..998af07 --- /dev/null +++ b/static/PostgreSQL/11225_tbl_TCG_MTG_Game_Session_Member_Audit.sql @@ -0,0 +1,15 @@ + +CREATE TABLE tcg.public.TCG_MTG_Game_Session_Member_Audit ( + audit_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY + , member_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_Audit_member_id + FOREIGN KEY (member_id) + REFERENCES tcg.public.TCG_MTG_Game_Session_Member(member_id) + , name_field TEXT NOT NULL + , value_prev TEXT + , value_new TEXT + , change_set_id INT NOT NULL + , CONSTRAINT FK_TCG_MTG_Game_Session_Member_Audit_change_set_id + FOREIGN KEY (change_set_id) + REFERENCES tcg.public.TCG_Change_Set(change_set_id) +); diff --git a/static/PostgreSQL/11226_tbl_TCG_MTG_Game_Session_Member_Temp.sql b/static/PostgreSQL/11226_tbl_TCG_MTG_Game_Session_Member_Temp.sql new file mode 100644 index 0000000..01a761d --- /dev/null +++ b/static/PostgreSQL/11226_tbl_TCG_MTG_Game_Session_Member_Temp.sql @@ -0,0 +1,16 @@ + +CREATE TABLE tcg.public.TCG_MTG_Game_Session_Member_Temp ( + temp_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY + , member_id INT + , game_id INT + , user_id INT + , is_permitted BOOLEAN + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT + , change_set_id INT + + , guid UUID NOT NULL +); diff --git a/static/PostgreSQL/30508_tri_TCG_User_Relationship.sql b/static/PostgreSQL/30508_tri_TCG_User_Relationship.sql new file mode 100644 index 0000000..afe95f1 --- /dev/null +++ b/static/PostgreSQL/30508_tri_TCG_User_Relationship.sql @@ -0,0 +1,84 @@ + +CREATE OR REPLACE FUNCTION tcg.public.FN_before_insert_TCG_User_Relationship() +RETURNS TRIGGER AS $$ +DECLARE + r_change_set RECORD; +BEGIN + NEW.created_on = COALESCE(NEW.created_on, CURRENT_TIMESTAMP); + NEW.updated_last_on = COALESCE(NEW.updated_last_on, CURRENT_TIMESTAMP); + + IF NEW.change_set_id IS NULL THEN + RAISE EXCEPTION 'Change Set ID must be provided.'; + END IF; + + SELECT * + INTO r_change_set + FROM tcg.public.TCG_Change_Set CHANGE_SET + WHERE NEW.change_set_id = CHANGE_SET.change_set_id + ; + + IF FOUND THEN + NEW.created_by_user_id := COALESCE(NEW.created_by_user_id, r_change_set.updated_last_by_user_id); + NEW.updated_last_by_user_id := COALESCE(NEW.updated_last_by_user_id, r_change_set.updated_last_by_user_id); + NEW.created_on := COALESCE(NEW.created_on, r_change_set.updated_last_on); + ELSE + RAISE EXCEPTION 'Change Set % not found.', NEW.change_set_id; + END IF; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql +; + +CREATE OR REPLACE FUNCTION tcg.public.FN_before_update_TCG_User_Relationship() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_last_on = CURRENT_TIMESTAMP; + + IF OLD.change_set_id IS NOT DISTINCT FROM NEW.change_set_id THEN + RAISE EXCEPTION 'New Change Set ID must be provided.'; + END IF; + + INSERT INTO tcg.public.TCG_User_Relationship_Audit ( + relationship_id + , name_field + , value_prev + , value_new + , change_set_id + ) + -- Changed follower_user_id + SELECT NEW.relationship_id, 'follower_user_id', OLD.follower_user_id::TEXT, NEW.follower_user_id::TEXT, NEW.change_set_id + WHERE OLD.follower_user_id IS NOT DISTINCT FROM NEW.follower_user_id + UNION + -- Changed following_user_id + SELECT NEW.relationship_id, 'following_user_id', OLD.following_user_id::TEXT, NEW.following_user_id::TEXT, NEW.change_set_id + WHERE OLD.following_user_id IS NOT DISTINCT FROM NEW.following_user_id + UNION + -- Changed is_following + SELECT NEW.relationship_id, 'is_following', OLD.is_following::TEXT, NEW.is_following::TEXT, NEW.change_set_id + WHERE OLD.is_following IS NOT DISTINCT FROM NEW.is_following + UNION + -- Changed is_blocked + SELECT NEW.relationship_id, 'is_blocked', OLD.is_blocked::TEXT, NEW.is_blocked::TEXT, NEW.change_set_id + WHERE OLD.is_blocked IS NOT DISTINCT FROM NEW.is_blocked + UNION + -- Changed active + SELECT NEW.relationship_id, 'active', OLD.active::TEXT, NEW.active::TEXT, NEW.change_set_id + WHERE OLD.active IS NOT DISTINCT FROM NEW.active + ; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql +; + +CREATE TRIGGER TRI_before_insert_TCG_User_Relationship + BEFORE INSERT ON tcg.public.TCG_User_Relationship + FOR EACH ROW + EXECUTE FUNCTION tcg.public.FN_before_insert_TCG_User_Relationship() +; +CREATE TRIGGER TRI_before_update_TCG_User_Relationship + BEFORE UPDATE ON tcg.public.TCG_User_Relationship + FOR EACH ROW + EXECUTE FUNCTION tcg.public.FN_before_update_TCG_User_Relationship() +; \ No newline at end of file diff --git a/static/PostgreSQL/31224_tri_TCG_MTG_Game_Session_Member.sql b/static/PostgreSQL/31224_tri_TCG_MTG_Game_Session_Member.sql new file mode 100644 index 0000000..3caa25a --- /dev/null +++ b/static/PostgreSQL/31224_tri_TCG_MTG_Game_Session_Member.sql @@ -0,0 +1,76 @@ + +CREATE OR REPLACE FUNCTION tcg.public.FN_before_insert_TCG_MTG_Game_Session_Member() +RETURNS TRIGGER AS $$ +DECLARE + r_change_set RECORD; +BEGIN + NEW.created_on = COALESCE(NEW.created_on, CURRENT_TIMESTAMP); + NEW.updated_last_on = COALESCE(NEW.updated_last_on, CURRENT_TIMESTAMP); + + IF NEW.change_set_id IS NULL THEN + RAISE EXCEPTION 'Change Set ID must be provided.'; + END IF; + + SELECT * + INTO r_change_set + FROM tcg.public.TCG_Change_Set CHANGE_SET + WHERE NEW.change_set_id = CHANGE_SET.change_set_id + ; + + IF FOUND THEN + NEW.created_by_user_id := COALESCE(NEW.created_by_user_id, r_change_set.updated_last_by_user_id); + NEW.updated_last_by_user_id := COALESCE(NEW.updated_last_by_user_id, r_change_set.updated_last_by_user_id); + NEW.created_on := COALESCE(NEW.created_on, r_change_set.updated_last_on); + ELSE + RAISE EXCEPTION 'Change Set % not found.', NEW.change_set_id; + END IF; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql +; + +CREATE OR REPLACE FUNCTION tcg.public.FN_before_update_TCG_MTG_Game_Session_Member() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_last_on = CURRENT_TIMESTAMP; + + IF OLD.change_set_id IS NOT DISTINCT FROM NEW.change_set_id THEN + RAISE EXCEPTION 'New Change Set ID must be provided.'; + END IF; + + INSERT INTO tcg.public.TCG_MTG_Game_Session_Member_Audit ( + member_id + , name_field + , value_prev + , value_new + , change_set_id + ) + -- Changed user_id + SELECT NEW.member_id, 'user_id', OLD.user_id::TEXT, NEW.user_id::TEXT, NEW.change_set_id + WHERE OLD.user_id IS NOT DISTINCT FROM NEW.user_id + UNION + -- Changed is_permitted + SELECT NEW.member_id, 'is_permitted', OLD.is_permitted::TEXT, NEW.is_permitted::TEXT, NEW.change_set_id + WHERE OLD.is_permitted IS NOT DISTINCT FROM NEW.is_permitted + UNION + -- Changed active + SELECT NEW.member_id, 'active', OLD.active::TEXT, NEW.active::TEXT, NEW.change_set_id + WHERE OLD.active IS NOT DISTINCT FROM NEW.active + ; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql +; + +CREATE TRIGGER TRI_before_insert_TCG_MTG_Game_Session_Member + BEFORE INSERT ON tcg.public.TCG_MTG_Game_Session_Member + FOR EACH ROW + EXECUTE FUNCTION tcg.public.FN_before_insert_TCG_MTG_Game_Session_Member() +; +CREATE TRIGGER TRI_before_update_TCG_MTG_Game_Session_Member + BEFORE UPDATE ON tcg.public.TCG_MTG_Game_Session_Member + FOR EACH ROW + EXECUTE FUNCTION tcg.public.FN_before_update_TCG_MTG_Game_Session_Member() +; \ No newline at end of file diff --git a/static/PostgreSQL/70505_usp_TCG_User_Login.sql b/static/PostgreSQL/70505_usp_TCG_User_Login.sql index afb38d4..865b27a 100644 --- a/static/PostgreSQL/70505_usp_TCG_User_Login.sql +++ b/static/PostgreSQL/70505_usp_TCG_User_Login.sql @@ -32,9 +32,10 @@ BEGIN o_success := FALSE; - DROP TABLE IF EXISTS Temp_User_Save_User; + -- DROP TABLE IF EXISTS Temp_User_Save_User; DROP TABLE IF EXISTS Temp_User_Save_Error; + /* CREATE TEMP TABLE Temp_User_Save_User ( user_id INT NOT NULL , user_auth0_id TEXT @@ -50,6 +51,7 @@ BEGIN , updated_last_by_user_id INT , change_set_id INT ); + */ CREATE TEMP TABLE Temp_User_Save_Error ( temp_id INT GENERATED ALWAYS AS IDENTITY @@ -68,6 +70,7 @@ BEGIN ); END IF; + /* INSERT INTO Temp_User_Save_User ( user_id , user_auth0_id @@ -85,7 +88,7 @@ BEGIN ) SELECT TCG_USER.user_id - , TCG_USER.user_auth0_id + , v_user_auth0_id , TCG_USER.firstname , TCG_USER.surname , TCG_USER.email @@ -98,8 +101,11 @@ BEGIN , COALESCE(TCG_USER.updated_last_by_user_id, v_bot_user_id) -- updated_last_by_user_id , TCG_USER.change_set_id FROM tcg.public.TCG_User TCG_USER - WHERE TCG_USER.user_auth0_id = v_user_auth0_id + WHERE + TCG_USER.user_auth0_id = v_user_auth0_id + OR TCG_USER.email = v_email ; + */ -- Outputs -- Change Set @@ -116,7 +122,14 @@ BEGIN IF NOT EXISTS (SELECT * FROM Temp_User_Save_Error T_ERROR WHERE T_ERROR.error_type_id <> v_warning_error_type_id LIMIT 1) THEN - IF NOT EXISTS (SELECT * FROM Temp_User_Save_User T_USER LIMIT 1) THEN + IF NOT EXISTS ( + SELECT * + FROM tcg.public.TCG_User TCG_USER + WHERE + TCG_USER.user_auth0_id = v_user_auth0_id + OR TCG_USER.email = v_email + LIMIT 1 + ) THEN -- RAISE EXCEPTION 'Valid User Auth0 ID required.'; -- New User @@ -148,7 +161,19 @@ BEGIN , v_bot_user_id -- updated_last_by_user_id , v_change_set_id -- change_set_id ); - + ELSEIF NOT EXISTS ( + SELECT * + FROM tcg.public.TCG_User TCG_USER + WHERE TCG_USER.user_auth0_id = v_user_auth0_id + ) THEN + UPDATE tcg.public.TCG_User TCG_USER + SET + user_auth0_id = v_user_auth0_id + , change_set_id = v_change_set_id + WHERE + TCG_USER.email = v_email + AND TCG_USER.active + ; END IF; ELSE -- Error @@ -252,3 +277,33 @@ SELECT * FROM tcg.public.TCG_User TCG_USER ORDER BY TCG_USER.user_id DESC ; + + +/* + + +SELECT * +FROM tcg.public.TCG_User TCG_USER +; + +INSERT INTO tcg.public.tcg_change_set ( + COMMENT, updated_last_by_user_id +) +VALUES ( 'Clear Auth0 id from Teddy.', 3); + +SELECT * +FROM tcg.public.tcg_change_set cs +ORDER BY cs.change_set_id DESC +; +UPDATE tcg.public.TCG_User TCG_USER +SET + user_auth0_id = NULL + , change_set_id = 224 +WHERE TCG_USER.user_id = 3 +; +DELETE FROM tcg.public.TCG_User TCG_USER +WHERE TCG_USER.user_id = 13 +; + +*/ + diff --git a/static/PostgreSQL/70508_fn_TCG_User_Relationship_Get_Many.sql b/static/PostgreSQL/70508_fn_TCG_User_Relationship_Get_Many.sql new file mode 100644 index 0000000..e5405fa --- /dev/null +++ b/static/PostgreSQL/70508_fn_TCG_User_Relationship_Get_Many.sql @@ -0,0 +1,131 @@ + +CREATE OR REPLACE FUNCTION tcg.public.FN_TCG_User_Relationship_Get_Many ( + a_get_inactive_user_relationship BOOLEAN + , a_get_all_user_follower BOOLEAN + , a_user_follower_ids TEXT + , a_get_all_user_following BOOLEAN + , a_user_following_ids TEXT + , a_get_inactive_user BOOLEAN + , a_require_all_id_filters_met BOOLEAN + , a_require_any_id_filters_met BOOLEAN +) +RETURNS TABLE ( + relationship_id INT + , follower_user_id INT + , following_user_id INT + , is_following BOOLEAN + , is_blocked BOOLEAN + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT + , change_set_id INT +) +LANGUAGE plpgsql +AS $$ +DECLARE + v_get_inactive_user_relationship BOOLEAN; + v_get_all_user_follower BOOLEAN; + v_user_follower_ids TEXT; + v_get_all_user_following BOOLEAN; + v_user_following_ids TEXT; + v_get_inactive_user BOOLEAN; + v_require_all_id_filters_met BOOLEAN; + v_require_any_id_filters_met BOOLEAN; +BEGIN + v_get_inactive_user_relationship := COALESCE(a_get_inactive_user_relationship, FALSE); + v_get_all_user_follower := COALESCE(a_get_all_user_follower, FALSE); + v_user_follower_ids := TRIM(COALESCE(a_user_follower_ids, '')); + v_get_all_user_following := COALESCE(a_get_all_user_following, FALSE); + v_user_following_ids := TRIM(COALESCE(a_user_following_ids, '')); + v_get_inactive_user := COALESCE(a_get_inactive_user, FALSE); + v_require_all_id_filters_met := COALESCE(a_require_all_id_filters_met, FALSE); + v_require_any_id_filters_met := COALESCE(a_require_any_id_filters_met, FALSE); + + -- Outputs + RETURN QUERY SELECT + RELATIONSHIP.relationship_id + , RELATIONSHIP.follower_user_id + , RELATIONSHIP.following_user_id + , RELATIONSHIP.is_following + , RELATIONSHIP.is_blocked + , RELATIONSHIP.active + , RELATIONSHIP.created_on + , RELATIONSHIP.created_by_user_id + , RELATIONSHIP.updated_last_on + , RELATIONSHIP.updated_last_by_user_id + , RELATIONSHIP.change_set_id + FROM tcg.public.TCG_User_Relationship RELATIONSHIP + INNER JOIN tcg.public.TCG_User USER_FOLLOWER ON RELATIONSHIP.follower_user_id = USER_FOLLOWER.user_id + INNER JOIN tcg.public.TCG_User USER_FOLLOWING ON RELATIONSHIP.following_user_id = USER_FOLLOWING.user_id + WHERE + ( + ( + NOT v_require_all_id_filters_met + AND NOT v_require_any_id_filters_met + ) + OR ( + v_require_all_id_filters_met + AND ( + v_get_all_user_follower + OR USER_FOLLOWER.user_id = ANY(string_to_array(v_user_follower_ids, ',')::INT[]) + ) + AND ( + v_get_all_user_following + OR USER_FOLLOWING.user_id = ANY(string_to_array(v_user_following_ids, ',')::INT[]) + ) + ) + OR ( + NOT v_require_all_id_filters_met + AND v_require_any_id_filters_met + AND ( + ( + v_get_all_user_follower + OR USER_FOLLOWER.user_id = ANY(string_to_array(v_user_follower_ids, ',')::INT[]) + ) + OR ( + v_get_all_user_following + OR USER_FOLLOWING.user_id = ANY(string_to_array(v_user_following_ids, ',')::INT[]) + ) + ) + ) + ) + AND ( + v_get_inactive_user_relationship + OR RELATIONSHIP.active + ) + AND ( + v_get_inactive_user + OR ( + USER_FOLLOWER.active + AND USER_FOLLOWING.active + ) + ) + ORDER BY + RELATIONSHIP.follower_user_id + , NOT RELATIONSHIP.is_following + , NOT RELATIONSHIP.is_blocked + , RELATIONSHIP.following_user_id + ; +END; +$$; + + +SELECT * +FROM tcg.public.FN_TCG_User_Relationship_Get_Many ( + a_get_inactive_user_relationship := FALSE + , a_get_all_user_follower := TRUE + , a_user_follower_ids := '' + , a_get_all_user_following := TRUE + , a_user_following_ids := '' + , a_get_inactive_user := FALSE + , a_require_all_id_filters_met := TRUE + , a_require_any_id_filters_met := FALSE +) +; + + +SELECT * +FROM tcg.public.TCG_User_Relationship +; diff --git a/static/PostgreSQL/70509_usp_TCG_User_Relationship_Save.sql b/static/PostgreSQL/70509_usp_TCG_User_Relationship_Save.sql new file mode 100644 index 0000000..bea071a --- /dev/null +++ b/static/PostgreSQL/70509_usp_TCG_User_Relationship_Save.sql @@ -0,0 +1,532 @@ + +CREATE OR REPLACE PROCEDURE tcg.public.USP_TCG_User_Relationship_Save ( + a_comment TEXT + , a_guid UUID + , a_user_id INT + , OUT o_success BOOLEAN +) +LANGUAGE plpgsql +AS $$ +DECLARE + v_bad_data_error_type_id INT; + v_change_set_id INT; + v_comment TEXT; + -- v_error_message TEXT; + v_guid UUID; + v_time_start TIMESTAMP; + v_user_id INT; + v_warning_error_type_id INT; +BEGIN + v_comment := TRIM(COALESCE(a_comment, '')); + v_guid := a_guid; + v_user_id := a_user_id; + + v_bad_data_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'BAD_DATA' LIMIT 1); + v_warning_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'WARNING' LIMIT 1); + v_time_start := CURRENT_TIMESTAMP; + + DROP TABLE IF EXISTS Temp_User_Relationship_Save_User; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_User_Relationship; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_Error; + + CREATE TEMP TABLE Temp_User_Relationship_Save_User ( + user_id INT NOT NULL + , user_auth0_id TEXT + , firstname TEXT + , surname TEXT + , email TEXT + , is_email_verified BOOLEAN + , is_super_user BOOLEAN + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT + , change_set_id INT + ); + + CREATE TEMP TABLE Temp_User_Relationship_Save_User_Relationship ( + temp_id INT NOT NULL + , relationship_id INT + , follower_user_id INT + , following_user_id INT + , is_following BOOLEAN + , is_blocked BOOLEAN + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT + , change_set_id INT + + , is_new BOOLEAN + , error_name TEXT + , is_duplicate BOOLEAN + ); + + CREATE TEMP TABLE Temp_User_Relationship_Save_Error ( + temp_id INT GENERATED ALWAYS AS IDENTITY + , error_type_id INT + , message TEXT + ); + + WITH Temp_User_Relationship AS ( + SELECT + RELATIONSHIP_T.temp_id + , CASE WHEN COALESCE(RELATIONSHIP_T.relationship_id, 0) < 1 + THEN RELATIONSHIP.relationship_id + ELSE RELATIONSHIP_T.relationship_id + END AS relationship_id + , RELATIONSHIP_T.follower_user_id + , RELATIONSHIP_T.following_user_id + , COALESCE(RELATIONSHIP_T.is_following, TRUE) AS is_following + , COALESCE(RELATIONSHIP_T.is_blocked, FALSE) AS is_blocked + , COALESCE(RELATIONSHIP_T.active, TRUE) AS active + , COALESCE(RELATIONSHIP_T.created_on, v_time_start) AS created_on + , COALESCE(RELATIONSHIP_T.created_by_user_id, v_user_id) AS created_by_user_id + , COALESCE(RELATIONSHIP_T.updated_last_on, v_time_start) AS updated_last_on + , COALESCE(RELATIONSHIP_T.updated_last_by_user_id, v_user_id) AS updated_last_by_user_id + , RELATIONSHIP_T.change_set_id + + , CASE WHEN RELATIONSHIP.relationship_id IS NULL THEN TRUE ELSE FALSE END AS is_new + FROM tcg.public.TCG_User_Relationship_Temp RELATIONSHIP_T + LEFT JOIN tcg.public.TCG_User_Relationship RELATIONSHIP + ON RELATIONSHIP_T.relationship_id = RELATIONSHIP.relationship_id + OR ( + COALESCE(RELATIONSHIP_T.relationship_id, 0) < 1 + AND RELATIONSHIP_T.follower_user_id = RELATIONSHIP.follower_user_id + AND RELATIONSHIP_T.following_user_id = RELATIONSHIP.following_user_id + ) + ) + INSERT INTO Temp_User_Relationship_Save_User_Relationship ( + temp_id + , relationship_id + , follower_user_id + , following_user_id + , is_following + , is_blocked + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + + , is_new + , error_name + ) + SELECT + T_RELATIONSHIP.temp_id + , T_RELATIONSHIP.relationship_id + , T_RELATIONSHIP.follower_user_id + , T_RELATIONSHIP.following_user_id + , T_RELATIONSHIP.is_following + , T_RELATIONSHIP.is_blocked + , T_RELATIONSHIP.active + , T_RELATIONSHIP.created_on + , T_RELATIONSHIP.created_by_user_id + , T_RELATIONSHIP.updated_last_on + , T_RELATIONSHIP.updated_last_by_user_id + , T_RELATIONSHIP.change_set_id + + , T_RELATIONSHIP.is_new + , CONCAT( + 'User Relationship { id: ' + , CAST(T_RELATIONSHIP.relationship_id AS VARCHAR) + , ', follower user id: ' + , CAST(T_RELATIONSHIP.follower_user_id AS VARCHAR) + , ', following user id: ' + , CAST(T_RELATIONSHIP.following_user_id AS VARCHAR) + , ', is following: ' + , CAST(T_RELATIONSHIP.is_following AS VARCHAR) + , ', is blocked: ' + , CAST(T_RELATIONSHIP.is_blocked AS VARCHAR) + , ' }' + ) -- error_name + FROM Temp_User_Relationship T_RELATIONSHIP -- tcg.public.TCG_User_Relationship_Temp RELATIONSHIP_T + -- LEFT JOIN tcg.public.TCG_User_Relationship RELATIONSHIP ON RELATIONSHIP_T.relationship_id = RELATIONSHIP.relationship_id + ; + + INSERT INTO Temp_User_Relationship_Save_User ( + user_id + , user_auth0_id + , firstname + , surname + , email + , is_email_verified + , is_super_user + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT + TCG_USER.user_id + , TCG_USER.user_auth0_id + , TCG_USER.firstname + , TCG_USER.surname + , TCG_USER.email + , TCG_USER.is_email_verified + , TCG_USER.is_super_user + , TCG_USER.active + , TCG_USER.created_on + , TCG_USER.created_by_user_id + , TCG_USER.updated_last_on + , TCG_USER.updated_last_by_user_id + , TCG_USER.change_set_id + FROM tcg.public.TCG_User TCG_USER + INNER JOIN Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + ON TCG_USER.user_id = T_RELATIONSHIP.follower_user_id + OR TCG_USER.user_id = T_RELATIONSHIP.following_user_id + ; + + -- Missing fields + WITH Relationship_Missing_Field AS ( + SELECT + T_RELATIONSHIP.temp_id + , 'follower_user_id' AS field + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + WHERE T_RELATIONSHIP.follower_user_id IS NULL + UNION + SELECT + T_RELATIONSHIP.temp_id + , 'following_user_id' AS field + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + WHERE T_RELATIONSHIP.following_user_id IS NULL + ) + INSERT INTO Temp_User_Relationship_Save_Error ( + error_type_id + , message + ) + SELECT + v_bad_data_error_type_id -- error_type_id + , CONCAT( + 'Missing mandatory field: ' + , RELATIONSHIP_MISSING_FIELD.field + , ' on ' + , T_RELATIONSHIP.error_name + , '.' + ) -- message + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + INNER JOIN Relationship_Missing_Field RELATIONSHIP_MISSING_FIELD ON T_RELATIONSHIP.temp_id = RELATIONSHIP_MISSING_FIELD.temp_id + ; + + -- Failed join fields + WITH Relationship_Failed_Join_Field AS ( + SELECT + T_RELATIONSHIP.temp_id + , 'follower_user_id' AS field + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + LEFT JOIN Temp_User_Relationship_Save_User T_USER ON T_RELATIONSHIP.follower_user_id = T_USER.user_id + WHERE T_USER.user_id IS NULL + UNION + SELECT + T_RELATIONSHIP.temp_id + , 'following_user_id' AS field + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + LEFT JOIN Temp_User_Relationship_Save_User T_USER ON T_RELATIONSHIP.following_user_id = T_USER.user_id + WHERE T_USER.user_id IS NULL + ) + INSERT INTO Temp_User_Relationship_Save_Error ( + error_type_id + , message + ) + SELECT + v_bad_data_error_type_id -- error_type_id + , CONCAT( + 'Failed relationship: ' + , RELATIONSHIP_FAILED_JOIN_FIELD.field + , ' on ' + , T_RELATIONSHIP.error_name + , '.' + ) -- message + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + INNER JOIN Relationship_Failed_Join_Field RELATIONSHIP_FAILED_JOIN_FIELD ON T_RELATIONSHIP.temp_id = RELATIONSHIP_FAILED_JOIN_FIELD.temp_id + ; + + -- Duplicate Relationship + WITH + All_Relationship AS ( + SELECT + T_RELATIONSHIP.temp_id + , T_RELATIONSHIP.follower_user_id + , T_RELATIONSHIP.following_user_id + , TRUE AS is_save_record + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + UNION + SELECT + NULL AS temp_id + , RELATIONSHIP.follower_user_id + , RELATIONSHIP.following_user_id + , FALSE AS is_save_record + FROM tcg.public.TCG_User_Relationship RELATIONSHIP + LEFT JOIN Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP ON RELATIONSHIP.relationship_id = T_RELATIONSHIP.relationship_id + WHERE + T_RELATIONSHIP.relationship_id IS NULL + AND RELATIONSHIP.active + ) + , Relationship_Follow_Pair AS ( + SELECT + ALL_RELATIONSHIP.follower_user_id + , ALL_RELATIONSHIP.following_user_id + , COUNT(*) AS count_pair + FROM All_Relationship ALL_RELATIONSHIP + GROUP BY + ALL_RELATIONSHIP.follower_user_id + , ALL_RELATIONSHIP.following_user_id + ) + , Duplicate_Relationship AS ( + SELECT + ALL_RELATIONSHIP.temp_id + , ALL_RELATIONSHIP.follower_user_id + , ALL_RELATIONSHIP.following_user_id + , CASE WHEN RELATIONSHIP_PAIR.count_pair = 1 THEN TRUE ELSE FALSE END AS is_unique + FROM All_Relationship ALL_RELATIONSHIP + INNER JOIN Relationship_Follow_Pair RELATIONSHIP_PAIR + ON ALL_RELATIONSHIP.follower_user_id = RELATIONSHIP_PAIR.follower_user_id + AND ALL_RELATIONSHIP.following_user_id = RELATIONSHIP_PAIR.following_user_id + ) + UPDATE Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + SET is_duplicate = NOT DUPLICATE_RELATIONSHIP.is_unique + FROM Duplicate_Relationship DUPLICATE_RELATIONSHIP + WHERE T_RELATIONSHIP.temp_id = DUPLICATE_RELATIONSHIP.temp_id + ; + + IF EXISTS ( + SELECT * + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + WHERE T_RELATIONSHIP.is_duplicate + LIMIT 1 + ) THEN + INSERT INTO Temp_User_Relationship_Save_Error ( + error_type_id + , message + ) + SELECT + v_bad_data_error_type_id -- error_type_id + , CONCAT( + 'Duplicate on ' + , T_RELATIONSHIP.error_name + ) -- message + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + WHERE T_RELATIONSHIP.is_duplicate + ; + END IF; + + -- Nothing to save + IF NOT EXISTS (SELECT * FROM Temp_User_Relationship_Save_User_Relationship LIMIT 1) THEN + INSERT INTO Temp_User_Relationship_Save_Error ( + error_type_id + , message + ) + VALUES ( + v_warning_error_type_id + , 'Nothing to save.' + ); + END IF; + + -- Outputs + -- Change Set + INSERT INTO tcg.public.TCG_Change_Set ( + comment + , updated_last_by_user_id + ) + VALUES ( + v_comment + , v_user_id + ) + RETURNING change_set_id INTO v_change_set_id + ; + + IF NOT EXISTS (SELECT * FROM Temp_User_Relationship_Save_Error T_ERROR WHERE T_ERROR.error_type_id <> v_warning_error_type_id LIMIT 1) THEN + + -- User relationship + INSERT INTO tcg.public.TCG_User_Relationship ( + follower_user_id + , following_user_id + , is_following + , is_blocked + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT + T_RELATIONSHIP.follower_user_id + , T_RELATIONSHIP.following_user_id + , T_RELATIONSHIP.is_following + , T_RELATIONSHIP.is_blocked + , T_RELATIONSHIP.active + , T_RELATIONSHIP.created_on + , T_RELATIONSHIP.created_by_user_id + , T_RELATIONSHIP.updated_last_on + , T_RELATIONSHIP.updated_last_by_user_id + , v_change_set_id -- change_set_id + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + WHERE + T_RELATIONSHIP.is_new = TRUE + AND T_RELATIONSHIP.active = TRUE + ORDER BY + T_RELATIONSHIP.is_following + , T_RELATIONSHIP.is_blocked + , T_RELATIONSHIP.follower_user_id + , T_RELATIONSHIP.following_user_id + ; + + UPDATE tcg.public.TCG_User_Relationship RELATIONSHIP + SET + follower_user_id = T_RELATIONSHIP.follower_user_id + , following_user_id = T_RELATIONSHIP.following_user_id + , is_following = T_RELATIONSHIP.is_following + , is_blocked = T_RELATIONSHIP.is_blocked + , active = T_RELATIONSHIP.active + , updated_last_on = v_time_start + , updated_last_by_user_id = v_user_id + , change_set_id = v_change_set_id + FROM Temp_User_Relationship_Save_User_Relationship T_RELATIONSHIP + WHERE + RELATIONSHIP.relationship_id = T_RELATIONSHIP.relationship_id + AND NOT T_RELATIONSHIP.is_new + ; + + ELSE + -- Error + INSERT INTO tcg.public.Error ( + guid + , error_type_id + , message + , display_order + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT + v_guid + , T_ERROR.error_type_id + , T_ERROR.message + , T_ERROR.temp_id + , v_time_start + , v_user_id + , v_time_start + , v_user_id + , v_change_set_id + FROM Temp_User_Relationship_Save_Error T_ERROR + LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON T_ERROR.error_type_id = ERROR_TYPE.error_type_id + ORDER BY T_ERROR.temp_id + ; + END IF; + + COMMIT; + + o_success := NOT EXISTS ( + SELECT * + FROM Temp_User_Relationship_Save_Error T_ERROR + WHERE T_ERROR.error_type_id <> v_warning_error_type_id + LIMIT 1 + ); + + DELETE FROM tcg.public.TCG_User_Relationship_Temp RELATIONSHIP_T WHERE RELATIONSHIP_T.guid = v_guid; + + DROP TABLE IF EXISTS Temp_User_Relationship_Save_User; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_User_Relationship; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_Error; +END; +$$; + + + +-- Call it with: +DO $$ +DECLARE + v_comment TEXT := 'User Relationship Save.'; + v_guid UUID; + v_user_id INT := 3; + v_success BOOLEAN; +BEGIN + v_guid := gen_random_uuid(); + + INSERT INTO tcg.public.TCG_User_Relationship_Temp ( + guid + , relationship_id + , follower_user_id + , following_user_id + , is_following + , is_blocked + , active + ) + VALUES + ( + v_guid + , NULL -- relationship_id + , 3 -- follower_user_id + , 4 -- following_user_id + , TRUE -- is_following + , FALSE -- is_blocked + , TRUE -- active + ) + , ( + v_guid + , NULL -- relationship_id + , 3 -- follower_user_id + , 5 -- following_user_id + , FALSE -- is_following + , TRUE -- is_blocked + , TRUE -- active + ) + , ( + v_guid + , NULL -- relationship_id + , 4 -- follower_user_id + , 3 -- following_user_id + , TRUE -- is_following + , FALSE -- is_blocked + , TRUE -- active + ) + ; + + CALL tcg.public.USP_TCG_User_Relationship_Save ( + v_comment -- a_comment + , v_guid -- a_guid + , v_user_id -- a_user_id + , v_success -- o_success + ); + RAISE NOTICE 'Success: %', CASE WHEN v_success THEN 'TRUE' ELSE 'FALSE' END; +END; +$$; + +SELECT * +-- DELETE +FROM tcg.public.Error ERROR +LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON ERROR.error_type_id = ERROR_TYPE.error_type_id +; +SELECT * +FROM tcg.public.Error_Type ERROR_TYPE +; +SELECT * +FROM tcg.public.TCG_Change_Set CHANGE_SET +ORDER BY CHANGE_SET.change_set_id DESC +; + + +/* +SELECT * +FROM tcg.public.TCG_MTG_Game +; +*/ + +SELECT * +-- DELETE +FROM tcg.public.TCG_User_Relationship_Temp RELATIONSHIP_T +; +SELECT * +-- DELETE +FROM tcg.public.TCG_User_Relationship RELATIONSHIP +; + + diff --git a/static/PostgreSQL/71150_usp_TCG_MTG_Inventory_Save.sql b/static/PostgreSQL/71150_usp_TCG_MTG_Inventory_Save.sql index cf83349..9096ab7 100644 --- a/static/PostgreSQL/71150_usp_TCG_MTG_Inventory_Save.sql +++ b/static/PostgreSQL/71150_usp_TCG_MTG_Inventory_Save.sql @@ -79,7 +79,7 @@ BEGIN , missing_mandatory_fields TEXT ); - CREATE TABLE Temp_MTG_Inventory_Save_Card ( + CREATE TEMP TABLE Temp_MTG_Inventory_Save_Card ( card_id INT NOT NULL , all_parts TEXT , arena_id INTEGER diff --git a/static/PostgreSQL/71200_fn_TCG_MTG_Deck_Get_Many.sql b/static/PostgreSQL/71200_fn_TCG_MTG_Deck_Get_Many.sql index 2c96e4c..fe49403 100644 --- a/static/PostgreSQL/71200_fn_TCG_MTG_Deck_Get_Many.sql +++ b/static/PostgreSQL/71200_fn_TCG_MTG_Deck_Get_Many.sql @@ -5,8 +5,13 @@ CREATE OR REPLACE FUNCTION tcg.public.FN_TCG_MTG_Deck_Get_Many ( , a_deck_ids TEXT , a_deck_names TEXT , a_commander_bracket_ids TEXT + , a_created_by_user_ids TEXT , a_include_commander_option BOOLEAN - , a_require_all_id_filters_met BOOLEAN + , a_get_all_game BOOLEAN + , a_get_inactive_game BOOLEAN + , a_game_ids TEXT + , a_filter_by_game_session_not_player BOOLEAN + , a_require_all_id_filters_met BOOLEAN , a_require_any_id_filters_met BOOLEAN , a_require_all_non_id_filters_met BOOLEAN , a_require_any_non_id_filters_met BOOLEAN @@ -30,7 +35,12 @@ DECLARE v_get_inactive_deck BOOLEAN; v_deck_ids TEXT; v_deck_names TEXT; + v_created_by_user_ids TEXT; v_include_commander_option BOOLEAN; + v_get_all_game BOOLEAN; + v_get_inactive_game BOOLEAN; + v_game_ids TEXT; + v_filter_by_game_session_not_player BOOLEAN; v_require_all_id_filters_met BOOLEAN; v_require_any_id_filters_met BOOLEAN; v_require_all_non_id_filters_met BOOLEAN; @@ -41,13 +51,19 @@ BEGIN v_deck_ids := TRIM(COALESCE(a_deck_ids, '')); v_deck_names := TRIM(COALESCE(a_deck_names, '')); v_include_commander_option := COALESCE(a_include_commander_option, TRUE); + v_created_by_user_ids := TRIM(COALESCE(a_created_by_user_ids, '')); + v_get_all_game := COALESCE(a_get_all_game, FALSE); + v_get_inactive_game := COALESCE(a_get_inactive_game, FALSE); + v_game_ids := TRIM(COALESCE(a_game_ids, '')); + v_filter_by_game_session_not_player := COALESCE(a_filter_by_game_session_not_player, TRUE); v_require_all_id_filters_met := COALESCE(a_require_all_id_filters_met, FALSE); v_require_any_id_filters_met := COALESCE(a_require_any_id_filters_met, FALSE); v_require_all_non_id_filters_met := COALESCE(a_require_all_non_id_filters_met, FALSE); v_require_any_non_id_filters_met := COALESCE(a_require_any_non_id_filters_met, FALSE); -- Outputs - RETURN QUERY SELECT + RETURN QUERY + SELECT DISTINCT DECK.deck_id , DECK.name , DECK.is_commander @@ -59,6 +75,9 @@ BEGIN , DECK.updated_last_by_user_id , DECK.change_set_id FROM tcg.public.TCG_MTG_Deck DECK + LEFT JOIN tcg.public.TCG_MTG_Game SESSION_GAME ON DECK.game_id = SESSION_GAME.game_id + LEFT JOIN tcg.public.TCG_MTG_Game_Player PLAYER ON DECK.deck_id = PLAYER.deck_id + LEFT JOIN tcg.public.TCG_MTG_Game PLAYER_GAME ON PLAYER.game_id = PLAYER_GAME.game_id WHERE ( ( @@ -69,7 +88,21 @@ BEGIN v_require_all_id_filters_met AND ( v_get_all_deck - OR DECK.deck_id = ANY(string_to_array(v_deck_ids, ',')::INT[]) + OR ( + DECK.deck_id = ANY(string_to_array(v_deck_ids, ',')::INT[]) + AND DECK.created_by_user_id = ANY(string_to_array(v_created_by_user_ids, ',')::INT[]) + AND ( + v_get_all_game + OR ( + v_filter_by_game_session_not_player + AND SESSION_GAME.game_id = ANY(string_to_array(v_game_ids, ',')::INT[]) + ) + OR ( + NOT v_filter_by_game_session_not_player + AND PLAYER.game_id = ANY(string_to_array(v_game_ids, ',')::INT[]) + ) + ) + ) ) ) OR ( @@ -78,6 +111,18 @@ BEGIN AND ( v_get_all_deck OR DECK.deck_id = ANY(string_to_array(v_deck_ids, ',')::INT[]) + OR DECK.created_by_user_id = ANY(string_to_array(v_created_by_user_ids, ',')::INT[]) + OR ( + v_get_all_game + OR ( + v_filter_by_game_session_not_player + AND SESSION_GAME.game_id = ANY(string_to_array(v_game_ids, ',')::INT[]) + ) + OR ( + NOT v_filter_by_game_session_not_player + AND PLAYER.game_id = ANY(string_to_array(v_game_ids, ',')::INT[]) + ) + ) ) ) ) @@ -113,6 +158,17 @@ BEGIN v_get_inactive_deck OR DECK.active ) + AND ( + v_get_inactive_game + OR ( + v_filter_by_game_session_not_player + AND SESSION_GAME.active + ) + OR ( + NOT v_filter_by_game_session_not_player + AND PLAYER_GAME.active + ) + ) ORDER BY DECK.name ; END; @@ -126,8 +182,13 @@ FROM tcg.public.FN_TCG_MTG_Deck_Get_Many ( , a_deck_ids := CAST(NULL AS TEXT) , a_deck_names := CAST(NULL AS TEXT) , a_commander_bracket_ids := CAST(NULL AS TEXT) - , a_include_commander_option := TRUE - , a_require_all_id_filters_met := FALSE + , a_include_commander_option := true + , a_created_by_user_ids := '3' + , a_get_all_game := FALSE + , a_get_inactive_game := FALSE + , a_game_ids := CAST(NULL AS TEXT) + , a_filter_by_game_session_not_player := TRUE + , a_require_all_id_filters_met := TRUE , a_require_any_id_filters_met := FALSE , a_require_all_non_id_filters_met := FALSE , a_require_any_non_id_filters_met := FALSE diff --git a/static/PostgreSQL/71208_fn_TCG_MTG_Game_Get_Many.sql b/static/PostgreSQL/71208_fn_TCG_MTG_Game_Get_Many.sql index 578d5dc..0425852 100644 --- a/static/PostgreSQL/71208_fn_TCG_MTG_Game_Get_Many.sql +++ b/static/PostgreSQL/71208_fn_TCG_MTG_Game_Get_Many.sql @@ -22,6 +22,8 @@ RETURNS TABLE ( , active BOOLEAN , created_on TIMESTAMP , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT ) LANGUAGE plpgsql AS $$ @@ -65,6 +67,8 @@ BEGIN , GAME.active , GAME.created_on , GAME.created_by_user_id + , GAME.updated_last_on + , GAME.updated_last_by_user_id FROM tcg.public.TCG_MTG_Game GAME INNER JOIN tcg.public.TCG_User CREATOR_USER ON GAME.created_by_user_id = CREATOR_USER.user_id WHERE diff --git a/static/PostgreSQL/71212_fn_TCG_MTG_Game_Player_Get_Many.sql b/static/PostgreSQL/71212_fn_TCG_MTG_Game_Player_Get_Many.sql index ddc9207..b5289ff 100644 --- a/static/PostgreSQL/71212_fn_TCG_MTG_Game_Player_Get_Many.sql +++ b/static/PostgreSQL/71212_fn_TCG_MTG_Game_Player_Get_Many.sql @@ -37,7 +37,7 @@ BEGIN v_require_any_id_filters_met := COALESCE(a_require_any_id_filters_met, FALSE); -- Outputs - + RETURN QUERY WITH User_Name AS ( SELECT TCG_USER.user_id @@ -46,31 +46,31 @@ BEGIN TRIM(COALESCE(TCG_USER.firstname, '')) <> '' AND TRIM(COALESCE(TCG_USER.surname, '')) <> '' THEN CONCAT( - TRIM(COALESCE(TCG_USER.firstname, '')) <> '' + TRIM(COALESCE(TCG_USER.firstname, '')) , ' ' - , TRIM(COALESCE(TCG_USER.surname, '')) <> '' + , TRIM(COALESCE(TCG_USER.surname, '')) ) WHEN TRIM(COALESCE(TCG_USER.firstname, '')) <> '' - THEN TRIM(COALESCE(TCG_USER.firstname, '')) <> '' - ELSE TRIM(COALESCE(TCG_USER.surname, '')) <> '' + THEN TRIM(COALESCE(TCG_USER.firstname, '')) + ELSE TRIM(COALESCE(TCG_USER.surname, '')) END AS name FROM tcg.public.TCG_User TCG_USER ) - RETURN QUERY SELECT + SELECT PLAYER.player_id , PLAYER.game_id , PLAYER.user_id , PLAYER.deck_id , CASE WHEN TRIM(COALESCE(PLAYER.name, '')) <> '' - THEN TRIM(COALESCE(PLAYER.name, '')) <> '' + THEN TRIM(COALESCE(PLAYER.name, '')) WHEN USER_NAME.name <> '' AND TRIM(COALESCE(DECK.name, '')) <> '' THEN CONCAT( - USER_NAME.name <> '' + USER_NAME.name , ' - ' - , TRIM(COALESCE(DECK.name, '')) <> '' + , TRIM(COALESCE(DECK.name, '')) ) ELSE CONCAT( 'Player ' diff --git a/static/PostgreSQL/71213_usp_TCG_MTG_Game_Player_Save.sql b/static/PostgreSQL/71213_usp_TCG_MTG_Game_Player_Save.sql index 8469272..15a1e7e 100644 --- a/static/PostgreSQL/71213_usp_TCG_MTG_Game_Player_Save.sql +++ b/static/PostgreSQL/71213_usp_TCG_MTG_Game_Player_Save.sql @@ -10,10 +10,17 @@ AS $$ DECLARE v_bad_data_error_type_id INT; v_change_set_id INT; + v_comment TEXT; -- v_error_message TEXT; + v_guid UUID; v_time_start TIMESTAMP; + v_user_id INT; v_warning_error_type_id INT; BEGIN + v_comment := TRIM(COALESCE(a_comment, '')); + v_guid := a_guid; + v_user_id := a_user_id; + v_bad_data_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'BAD_DATA' LIMIT 1); v_warning_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'WARNING' LIMIT 1); v_time_start := CURRENT_TIMESTAMP; @@ -22,9 +29,10 @@ BEGIN DROP TABLE IF EXISTS Temp_MTG_Player_Save_User; DROP TABLE IF EXISTS Temp_MTG_Player_Save_Deck; DROP TABLE IF EXISTS Temp_MTG_Player_Save_Player; + DROP TABLE IF EXISTS Temp_MTG_Player_Save_User_Relationship; DROP TABLE IF EXISTS Temp_MTG_Player_Save_Error; - CREATE TABLE Temp_MTG_Player_Save_Game ( + CREATE TEMP TABLE Temp_MTG_Player_Save_Game ( game_id INT NOT NULL , notes TEXT , is_commander BOOLEAN @@ -33,6 +41,7 @@ BEGIN , location_name TEXT , start_on TIMESTAMP , end_on TIMESTAMP + , starting_life INT , active BOOLEAN , created_on TIMESTAMP , created_by_user_id INT @@ -41,7 +50,7 @@ BEGIN , change_set_id INT ); - CREATE TABLE Temp_MTG_Player_Save_User ( + CREATE TEMP TABLE Temp_MTG_Player_Save_User ( user_id INT NOT NULL , user_auth0_id TEXT , firstname TEXT @@ -57,7 +66,7 @@ BEGIN , change_set_id INT ); - CREATE TABLE Temp_MTG_Player_Save_Deck ( + CREATE TEMP TABLE Temp_MTG_Player_Save_Deck ( deck_id INT NOT NULL , name TEXT , is_commander BOOLEAN @@ -70,7 +79,7 @@ BEGIN , change_set_id INT ); - CREATE TABLE Temp_MTG_Player_Save_Player ( + CREATE TEMP TABLE Temp_MTG_Player_Save_Player ( temp_id INT NOT NULL , player_id INT , game_id INT @@ -90,12 +99,57 @@ BEGIN , is_duplicate BOOLEAN ); + CREATE TEMP TABLE Temp_MTG_Player_Save_User_Relationship ( + relationship_id INT + , follower_user_id INT + , following_user_id INT + , is_following BOOLEAN + , is_blocked BOOLEAN + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT + , change_set_id INT + + , is_new BOOLEAN + , error_name TEXT + ); + CREATE TEMP TABLE Temp_MTG_Player_Save_Error ( temp_id INT GENERATED ALWAYS AS IDENTITY , error_type_id INT , message TEXT ); + WITH Temp_Player AS ( + SELECT + PLAYER_T.temp_id + , CASE WHEN COALESCE(PLAYER_T.player_id, 0) < 1 + THEN PLAYER.player_id + ELSE PLAYER_T.player_id + END AS player_id + , PLAYER_T.game_id + , PLAYER_T.user_id + , PLAYER_T.deck_id + , PLAYER_T.name + , PLAYER_T.notes + , PLAYER_T.display_order + , COALESCE(PLAYER_T.active, TRUE) AS active + , COALESCE(PLAYER_T.created_on, v_time_start) AS created_on + , COALESCE(PLAYER_T.created_by_user_id, v_user_id) AS created_by_user_id + , COALESCE(PLAYER_T.updated_last_on, v_time_start) AS updated_last_on + , COALESCE(PLAYER_T.updated_last_by_user_id, v_user_id) AS updated_last_by_user_id + FROM tcg.public.TCG_MTG_Game_Player_Temp PLAYER_T + LEFT JOIN tcg.public.TCG_MTG_Game_Player PLAYER + ON PLAYER_T.player_id = PLAYER.player_id + OR ( + COALESCE(PLAYER_T.player_id, 0) < 1 + AND PLAYER_T.game_id = PLAYER.game_id + AND PLAYER_T.display_order = PLAYER.display_order + ) + WHERE PLAYER_T.guid = v_guid + ) INSERT INTO Temp_MTG_Player_Save_Player ( temp_id , player_id @@ -115,37 +169,35 @@ BEGIN , error_name ) SELECT - PLAYER_T.temp_id - , PLAYER_T.player_id - , PLAYER_T.game_id - , PLAYER_T.user_id - , PLAYER_T.deck_id - , PLAYER_T.name - , PLAYER_T.notes - , PLAYER_T.display_order - , COALESCE(PLAYER_T.active, TRUE) - , COALESCE(PLAYER_T.created_on, v_time_start) -- created_on - , COALESCE(PLAYER_T.created_by_user_id, a_user_id) -- created_by_user_id - , COALESCE(PLAYER_T.updated_last_on, v_time_start) -- updated_last_on - , COALESCE(PLAYER_T.updated_last_by_user_id, a_user_id) -- updated_last_by_user_id + T_PLAYER.temp_id + , T_PLAYER.player_id + , T_PLAYER.game_id + , T_PLAYER.user_id + , T_PLAYER.deck_id + , T_PLAYER.name + , T_PLAYER.notes + , T_PLAYER.display_order + , T_PLAYER.active + , T_PLAYER.created_on + , T_PLAYER.created_by_user_id + , T_PLAYER.updated_last_on + , T_PLAYER.updated_last_by_user_id - , CASE WHEN PLAYER.player_id IS NULL THEN TRUE ELSE FALSE END AS is_new + , CASE WHEN T_PLAYER.player_id IS NULL THEN TRUE ELSE FALSE END AS is_new , CONCAT( 'Player { id: ' - , CAST(PLAYER_T.player_id AS VARCHAR) + , CAST(T_PLAYER.player_id AS VARCHAR) , ', temp id: ' - , CAST(PLAYER_T.temp_id AS VARCHAR) + , CAST(T_PLAYER.temp_id AS VARCHAR) , ', display order: ' - , CAST(PLAYER_T.display_order AS VARCHAR) + , CAST(T_PLAYER.display_order AS VARCHAR) , ', game id: ' - , CAST(PLAYER_T.game_id AS VARCHAR) + , CAST(T_PLAYER.game_id AS VARCHAR) , ', name: ' - , PLAYER_T.name + , T_PLAYER.name , ' }' ) -- error_name - FROM tcg.public.TCG_MTG_Game_Player_Temp PLAYER_T - LEFT JOIN tcg.public.TCG_MTG_Game_Player PLAYER ON PLAYER_T.player_id = PLAYER.player_id - WHERE PLAYER_T.guid = a_guid + FROM Temp_Player T_PLAYER ; INSERT INTO Temp_MTG_Player_Save_Game ( @@ -157,6 +209,7 @@ BEGIN , location_name , start_on , end_on + , starting_life , active , created_on , created_by_user_id @@ -164,7 +217,7 @@ BEGIN , updated_last_by_user_id , change_set_id ) - SELECT + SELECT DISTINCT GAME.game_id , GAME.notes , GAME.is_commander @@ -173,6 +226,7 @@ BEGIN , GAME.location_name , GAME.start_on , GAME.end_on + , GAME.starting_life , GAME.active , GAME.created_on , GAME.created_by_user_id @@ -180,7 +234,7 @@ BEGIN , GAME.updated_last_by_user_id , GAME.change_set_id FROM tcg.public.TCG_MTG_Game GAME - INNER JOIN Temp_MTG_Player_Save_Player PLAYER ON GAME.game_id = PLAYER.game_id + INNER JOIN Temp_MTG_Player_Save_Player PLAYER_T ON GAME.game_id = PLAYER_T.game_id ; INSERT INTO Temp_MTG_Player_Save_User ( @@ -198,7 +252,7 @@ BEGIN , updated_last_by_user_id , change_set_id ) - SELECT + SELECT DISTINCT TCG_USER.user_id , TCG_USER.user_auth0_id , TCG_USER.firstname @@ -213,7 +267,7 @@ BEGIN , TCG_USER.updated_last_by_user_id , TCG_USER.change_set_id FROM tcg.public.TCG_User TCG_USER - INNER JOIN Temp_MTG_Player_Save_Player PLAYER ON TCG_USER.user_id = PLAYER.user_id + INNER JOIN Temp_MTG_Player_Save_Player PLAYER_T ON TCG_USER.user_id = PLAYER_T.user_id ; INSERT INTO Temp_MTG_Player_Save_Deck ( @@ -243,6 +297,90 @@ BEGIN INNER JOIN Temp_MTG_Player_Save_Player PLAYER ON DECK.deck_id = DECK.deck_id ; + WITH + All_Game_User_Link AS ( + SELECT + T_GAME.game_id + , T_USER.user_id + FROM Temp_MTG_Player_Save_Game T_GAME + CROSS JOIN Temp_MTG_Player_Save_User T_USER + WHERE + T_GAME.active + AND T_USER.active + ) + , All_User_Relationship AS ( + SELECT DISTINCT + RELATIONSHIP.relationship_id + , GAME_USER_FOLLOWER.user_id AS follower_user_id + , GAME_USER_FOLLOWING.user_id AS following_user_id + , COALESCE(RELATIONSHIP.is_following, TRUE) AS is_following + , COALESCE(RELATIONSHIP.is_blocked, FALSE) AS is_blocked + , COALESCE(RELATIONSHIP.active, TRUE) AS active + , COALESCE(RELATIONSHIP.created_on, v_time_start) AS created_on + , COALESCE(RELATIONSHIP.created_by_user_id, v_user_id) AS created_by_user_id + , COALESCE(RELATIONSHIP.updated_last_on, v_time_start) AS updated_last_on + , COALESCE(RELATIONSHIP.updated_last_by_user_id, v_user_id) AS updated_last_by_user_id + , RELATIONSHIP.change_set_id + + , CASE WHEN RELATIONSHIP.relationship_id IS NULL THEN TRUE ELSE FALSE END AS Is_New + FROM All_Game_User_Link GAME_USER_FOLLOWER + CROSS JOIN All_Game_User_Link GAME_USER_FOLLOWING + LEFT JOIN tcg.public.TCG_User_Relationship RELATIONSHIP + ON GAME_USER_FOLLOWER.user_id = RELATIONSHIP.follower_user_id + AND GAME_USER_FOLLOWING.user_id = RELATIONSHIP.following_user_id + WHERE + GAME_USER_FOLLOWER.user_id <> GAME_USER_FOLLOWING.user_id + AND GAME_USER_FOLLOWER.game_id = GAME_USER_FOLLOWING.game_id + ) + INSERT INTO Temp_MTG_Player_Save_User_Relationship ( + relationship_id + , follower_user_id + , following_user_id + , is_following + , is_blocked + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + + , is_new + , error_name + ) + SELECT + ALL_RELATIONSHIP.relationship_id + , ALL_RELATIONSHIP.follower_user_id + , ALL_RELATIONSHIP.following_user_id + , ALL_RELATIONSHIP.is_following + , ALL_RELATIONSHIP.is_blocked + , ALL_RELATIONSHIP.active + , ALL_RELATIONSHIP.created_on + , ALL_RELATIONSHIP.created_by_user_id + , ALL_RELATIONSHIP.updated_last_on + , ALL_RELATIONSHIP.updated_last_by_user_id + , ALL_RELATIONSHIP.change_set_id + + , ALL_RELATIONSHIP.Is_New + , CONCAT( + 'User Relationship { id: ' + , CAST(ALL_RELATIONSHIP.relationship_id AS VARCHAR) + , ', follower user id: ' + , CAST(ALL_RELATIONSHIP.follower_user_id AS VARCHAR) + , ', following user id: ' + , CAST(ALL_RELATIONSHIP.following_user_id AS VARCHAR) + , ', is following: ' + , CAST(ALL_RELATIONSHIP.is_following AS VARCHAR) + , ', is blocked: ' + , CAST(ALL_RELATIONSHIP.is_blocked AS VARCHAR) + , ' is new: ' + , CAST(ALL_RELATIONSHIP.is_new AS VARCHAR) + , ' }' + ) -- error_name + FROM All_User_Relationship ALL_RELATIONSHIP + -- WHERE ALL_RELATIONSHIP.Is_New + ; + -- Missing fields WITH Player_Missing_Field AS ( SELECT @@ -354,7 +492,7 @@ BEGIN SELECT ALL_PLAYER.game_id , ALL_PLAYER.display_order - , COUNT(*) AS count + , COUNT(*) AS count_display_order FROM All_Player ALL_PLAYER GROUP BY ALL_PLAYER.game_id @@ -364,7 +502,7 @@ BEGIN SELECT ALL_PLAYER.game_id , ALL_PLAYER.deck_id - , COUNT(*) AS count + , COUNT(*) AS count_deck FROM All_Player ALL_PLAYER GROUP BY ALL_PLAYER.game_id @@ -377,14 +515,21 @@ BEGIN , ALL_PLAYER.deck_id , ALL_PLAYER.display_order -- , CASE WHEN CARD.temp_id IS NULL THEN TRUE ELSE FALSE END AS is_unique - , CASE WHEN PLAYER_DECK.count = 1 THEN TRUE ELSE FALSE END AS is_unique_deck - , CASE WHEN PLAYER_DISPLAY_ORDER.count = 1 THEN TRUE ELSE FALSE END AS is_unique_display_order + , CASE WHEN PLAYER_DECK.count_deck = 1 THEN TRUE ELSE FALSE END AS is_unique_deck + , CASE WHEN PLAYER_DISPLAY_ORDER.count_display_order = 1 THEN TRUE ELSE FALSE END AS is_unique_display_order FROM All_Player ALL_PLAYER - INNER JOIN Player_Deck PLAYER_DECK ON PLAYER.deck_id = PLAYER_DECK.deck_id - INNER JOIN Player_Display_Order PLAYER_DISPLAY_ORDER ON PLAYER.display_order = PLAYER_DISPLAY_ORDER.display_order + INNER JOIN Player_Deck PLAYER_DECK + ON ALL_PLAYER.game_id = PLAYER_DECK.game_id + AND ALL_PLAYER.deck_id = PLAYER_DECK.deck_id + INNER JOIN Player_Display_Order PLAYER_DISPLAY_ORDER + ON ALL_PLAYER.game_id = PLAYER_DISPLAY_ORDER.game_id + AND ALL_PLAYER.display_order = PLAYER_DISPLAY_ORDER.display_order ) UPDATE Temp_MTG_Player_Save_Player T_PLAYER - SET is_duplicate = CASE WHEN NOT ( is_unique_deck AND is_unique_display_order ) THEN TRUE ELSE FALSE END + SET is_duplicate = CASE WHEN NOT ( + DUPLICATE_PLAYER.is_unique_deck + AND DUPLICATE_PLAYER.is_unique_display_order + ) THEN TRUE ELSE FALSE END FROM Duplicate_Player DUPLICATE_PLAYER WHERE T_PLAYER.temp_id = DUPLICATE_PLAYER.temp_id ; @@ -422,6 +567,29 @@ BEGIN ); END IF; + /* + INSERT INTO Temp_MTG_Player_Save_Error ( + error_type_id + , message + ) + SELECT + v_warning_error_type_id AS error_type_id + , CONCAT( + 'Users: ' + , STRING_AGG(T_PLAYER.error_name, ', ') + ) AS message + FROM Temp_MTG_Player_Save_Player T_PLAYER + UNION + SELECT + v_warning_error_type_id AS error_type_id + , CONCAT( + 'User relationships: ' + , STRING_AGG(T_RELATIONSHIP.error_name, ', ') + ) AS message + FROM Temp_MTG_Player_Save_User_Relationship T_RELATIONSHIP + ; + */ + -- Outputs -- Change Set INSERT INTO tcg.public.TCG_Change_Set ( @@ -429,14 +597,42 @@ BEGIN , updated_last_by_user_id ) VALUES ( - a_comment - , a_user_id + v_comment + , v_user_id ) RETURNING change_set_id INTO v_change_set_id ; IF NOT EXISTS (SELECT * FROM Temp_MTG_Player_Save_Error T_ERROR WHERE T_ERROR.error_type_id <> v_warning_error_type_id LIMIT 1) THEN + -- User relationship + INSERT INTO tcg.public.TCG_User_Relationship ( + follower_user_id + , following_user_id + , is_following + , is_blocked + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT + T_RELATIONSHIP.follower_user_id + , T_RELATIONSHIP.following_user_id + , T_RELATIONSHIP.is_following + , T_RELATIONSHIP.is_blocked + , T_RELATIONSHIP.active + , T_RELATIONSHIP.created_on + , T_RELATIONSHIP.created_by_user_id + , T_RELATIONSHIP.updated_last_on + , T_RELATIONSHIP.updated_last_by_user_id + , v_change_set_id -- change_set_id + FROM Temp_MTG_Player_Save_User_Relationship T_RELATIONSHIP + WHERE T_RELATIONSHIP.is_new + ; + -- Player INSERT INTO tcg.public.TCG_MTG_Game_Player ( game_id @@ -460,11 +656,11 @@ BEGIN , T_PLAYER.notes , T_PLAYER.display_order , T_PLAYER.active - , v_time_start -- created_on - , a_user_id -- created_by_user_id - , v_time_start -- updated_last_on - , a_user_id -- updated_last_by_user_id - , v_change_set_id -- change_set_id + , T_PLAYER.created_on + , T_PLAYER.created_by_user_id + , T_PLAYER.updated_last_on + , T_PLAYER.updated_last_by_user_id + , v_change_set_id -- change_set_id FROM Temp_MTG_Player_Save_Player T_PLAYER LEFT JOIN Temp_MTG_Player_Save_Game T_GAME ON T_PLAYER.game_id = T_GAME.game_id WHERE @@ -485,42 +681,43 @@ BEGIN , display_order = T_PLAYER.display_order , active = T_PLAYER.active , updated_last_on = v_time_start - , updated_last_by_user_id = a_user_id + , updated_last_by_user_id = v_user_id , change_set_id = v_change_set_id FROM Temp_MTG_Player_Save_Player T_PLAYER WHERE PLAYER.player_id = T_PLAYER.player_id AND NOT T_PLAYER.is_new ; - ELSE - -- Error - INSERT INTO tcg.public.Error ( - guid - , error_type_id - , message - , display_order - , created_on - , created_by_user_id - , updated_last_on - , updated_last_by_user_id - , change_set_id - ) - SELECT - a_guid - , T_ERROR.error_type_id - , T_ERROR.message - , T_ERROR.temp_id - , v_time_start - , a_user_id - , v_time_start - , a_user_id - , v_change_set_id - FROM Temp_MTG_Player_Save_Error T_ERROR - LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON T_ERROR.error_type_id = ERROR_TYPE.error_type_id - ORDER BY T_ERROR.temp_id - ; + END IF; + -- Error + INSERT INTO tcg.public.Error ( + guid + , error_type_id + , message + , display_order + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT + v_guid + , T_ERROR.error_type_id + , T_ERROR.message + , T_ERROR.temp_id + , v_time_start + , v_user_id + , v_time_start + , v_user_id + , v_change_set_id + FROM Temp_MTG_Player_Save_Error T_ERROR + LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON T_ERROR.error_type_id = ERROR_TYPE.error_type_id + ORDER BY T_ERROR.temp_id + ; + COMMIT; o_success := NOT EXISTS ( @@ -530,12 +727,13 @@ BEGIN LIMIT 1 ); - DELETE FROM tcg.public.TCG_MTG_Game_Player_Temp PLAYER_T WHERE PLAYER_T.guid = a_guid; + DELETE FROM tcg.public.TCG_MTG_Game_Player_Temp PLAYER_T WHERE PLAYER_T.guid = v_guid; DROP TABLE IF EXISTS Temp_MTG_Player_Save_Game; DROP TABLE IF EXISTS Temp_MTG_Player_Save_User; DROP TABLE IF EXISTS Temp_MTG_Player_Save_Deck; DROP TABLE IF EXISTS Temp_MTG_Player_Save_Player; + DROP TABLE IF EXISTS Temp_MTG_Player_Save_User_Relationship; DROP TABLE IF EXISTS Temp_MTG_Player_Save_Error; END; $$; @@ -657,5 +855,14 @@ FROM tcg.public.TCG_MTG_Game_Player PLAYER LEFT JOIN tcg.public.TCG_MTG_Game GAME ON PLAYER.game_id = GAME.game_id ; +SELECT * +-- DELETE +FROM tcg.public.TCG_User_Relationship_Audit RELATIONSHIP_AUDIT +; +SELECT * +-- DELETE +FROM tcg.public.TCG_User_Relationship RELATIONSHIP +; + diff --git a/static/PostgreSQL/71221_usp_TCG_MTG_Game_Round_Damage_Save.sql b/static/PostgreSQL/71221_usp_TCG_MTG_Game_Round_Damage_Save.sql index c29d247..0fd035b 100644 --- a/static/PostgreSQL/71221_usp_TCG_MTG_Game_Round_Damage_Save.sql +++ b/static/PostgreSQL/71221_usp_TCG_MTG_Game_Round_Damage_Save.sql @@ -10,11 +10,19 @@ AS $$ DECLARE v_bad_data_error_type_id INT; v_change_set_id INT; + v_commander_damage_limit INT := 21; + v_comment TEXT; -- v_error_message TEXT; + v_guid UUID; v_no_permission_error_type_id INT; v_time_start TIMESTAMP; + v_user_id INT; v_warning_error_type_id INT; BEGIN + v_comment := TRIM(COALESCE(a_comment, '')); + v_guid := a_guid; + v_user_id := a_user_id; + v_bad_data_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'BAD_DATA' LIMIT 1); v_no_permission_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'NO_PERMISSION' LIMIT 1); v_warning_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'WARNING' LIMIT 1); @@ -24,6 +32,7 @@ BEGIN DROP TABLE IF EXISTS Temp_MTG_Round_Damage_Save_Player; DROP TABLE IF EXISTS Temp_MTG_Round_Damage_Save_Round; DROP TABLE IF EXISTS Temp_MTG_Round_Damage_Save_Round_Player_Damage; + DROP TABLE IF EXISTS Temp_MTG_Round_Damage_Save_Player_Round_Link; DROP TABLE IF EXISTS Temp_MTG_Round_Damage_Save_Error; CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Game ( @@ -35,12 +44,17 @@ BEGIN , location_name TEXT , start_on TIMESTAMP , end_on TIMESTAMP + , starting_life INT , active BOOLEAN , created_on TIMESTAMP , created_by_user_id INT , updated_last_on TIMESTAMP , updated_last_by_user_id INT , change_set_id INT + + , max_round_display_order INT + , count_players INT + , duration INTERVAL ); CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Player ( @@ -57,6 +71,15 @@ BEGIN , updated_last_on TIMESTAMP , updated_last_by_user_id INT , change_set_id INT + + , round_display_order_eliminated INT + , final_player_damage_round_id INT + , placement INT + , max_total_commander_damage_received INT + , total_commander_damage_dealt INT + , total_damage_received INT + , total_life_gained INT + , total_commander_deaths INT ); CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Round ( @@ -75,6 +98,7 @@ BEGIN , is_new BOOLEAN , error_name TEXT , is_duplicate BOOLEAN DEFAULT FALSE + , count_survivors INT ); CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Round_Player_Damage ( @@ -100,13 +124,26 @@ BEGIN , is_duplicate BOOLEAN DEFAULT FALSE ); + CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Player_Round_Link ( + game_id INT + , player_id INT + , round_id INT + + , is_eliminated BOOLEAN + , max_total_commander_damage_received INT + , total_commander_damage_dealt INT + , total_damage_received INT + , total_commander_deaths INT + , total_life_gained INT + ); + CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Error ( temp_id INT GENERATED ALWAYS AS IDENTITY , error_type_id INT , message TEXT ); - IF NOT EXISTS (SELECT * FROM tcg.public.TCG_User TCG_USER WHERE TCG_USER.user_id = a_user_id LIMIT 1) THEN + IF NOT EXISTS (SELECT * FROM tcg.public.TCG_User TCG_USER WHERE TCG_USER.user_id = v_user_id LIMIT 1) THEN INSERT INTO Temp_MTG_Round_Damage_Save_Error ( error_type_id , message @@ -115,12 +152,36 @@ BEGIN v_no_permission_error_type_id -- error_type_id , CONCAT( 'User does not exist: ' - , CAST(a_user_id AS VARCHAR) + , CAST(v_user_id AS VARCHAR) , '.' ) -- message ); END IF; + WITH Temp_Round AS ( + SELECT + ROUND_T.temp_id + , CASE WHEN COALESCE(ROUND_T.round_id, 0) < 1 + THEN COALESCE(TCG_ROUND.round_id, ROUND_T.round_id, 0) + ELSE ROUND_T.round_id + END AS round_id + , ROUND_T.game_id + , ROUND_T.notes + , ROUND_T.display_order + , COALESCE(ROUND_T.active, TRUE) AS active + , COALESCE(ROUND_T.created_on, v_time_start) AS created_on + , COALESCE(ROUND_T.created_by_user_id, v_user_id) AS created_by_user_id + , COALESCE(ROUND_T.updated_last_on, v_time_start) AS updated_last_on + , COALESCE(ROUND_T.updated_last_by_user_id, v_user_id) AS updated_last_by_user_id FROM tcg.public.TCG_MTG_Game_Round_Temp ROUND_T + LEFT JOIN tcg.public.TCG_MTG_Game_Round TCG_ROUND + ON ROUND_T.round_id = TCG_ROUND.round_id + OR ( + COALESCE(ROUND_T.round_id, 0) < 1 + AND ROUND_T.game_id = TCG_ROUND.game_id + AND ROUND_T.display_order = TCG_ROUND.display_order + ) + WHERE ROUND_T.guid = v_guid + ) INSERT INTO Temp_MTG_Round_Damage_Save_Round ( temp_id , round_id @@ -137,40 +198,71 @@ BEGIN , error_name ) SELECT - ROUND_T.temp_id - , ROUND_T.round_id - , ROUND_T.game_id - , ROUND_T.notes - , ROUND_T.display_order - , COALESCE(ROUND_T.active, TRUE) - , COALESCE(ROUND_T.created_on, v_time_start) -- created_on - , COALESCE(ROUND_T.created_by_user_id, a_user_id) -- created_by_user_id - , COALESCE(ROUND_T.updated_last_on, v_time_start) -- updated_last_on - , COALESCE(ROUND_T.updated_last_by_user_id, a_user_id) -- updated_last_by_user_id + T_ROUND.temp_id + , T_ROUND.round_id + , T_ROUND.game_id + , T_ROUND.notes + , T_ROUND.display_order + , T_ROUND.active + , T_ROUND.created_on + , T_ROUND.created_by_user_id + , T_ROUND.updated_last_on + , T_ROUND.updated_last_by_user_id , CASE WHEN TCG_ROUND.round_id IS NULL THEN TRUE ELSE FALSE END AS is_new , CONCAT( 'Round { id: ' - , CAST(ROUND_T.round_id AS VARCHAR) + , CAST(T_ROUND.round_id AS VARCHAR) , ', temp id: ' - , CAST(ROUND_T.temp_id AS VARCHAR) + , CAST(T_ROUND.temp_id AS VARCHAR) , ', display order: ' - , CAST(ROUND_T.display_order AS VARCHAR) + , CAST(T_ROUND.display_order AS VARCHAR) , ', game id: ' - , CAST(ROUND_T.game_id AS VARCHAR) + , CAST(T_ROUND.game_id AS VARCHAR) , ' }' - ) -- error_name - FROM tcg.public.TCG_MTG_Game_Round_Temp ROUND_T - LEFT JOIN tcg.public.TCG_MTG_Game_Round TCG_ROUND - ON ROUND_T.round_id = TCG_ROUND.round_id - OR ( - COALESCE(ROUND_T.round_id, 0) < 1 - AND ROUND_T.game_id = TCG_ROUND.game_id - AND ROUND_T.display_order = TCG_ROUND.display_order - ) - WHERE ROUND_T.guid = a_guid + ) AS error_name + FROM Temp_Round T_ROUND + LEFT JOIN tcg.public.TCG_MTG_Game_Round TCG_ROUND ON T_ROUND.round_id = TCG_ROUND.round_id ; + WITH Temp_Player_Damage AS ( + SELECT + PLAYER_DAMAGE_T.temp_id + , CASE WHEN COALESCE(PLAYER_DAMAGE_T.damage_id, 0) < 1 + THEN COALESCE(PLAYER_DAMAGE.damage_id, PLAYER_DAMAGE_T.damage_id, 0) + ELSE PLAYER_DAMAGE_T.damage_id + END AS damage_id + , T_ROUND.temp_id AS temp_round_id + , PLAYER_DAMAGE_T.round_id + , PLAYER_DAMAGE_T.player_id + , PLAYER_DAMAGE_T.received_from_commander_player_id + , ABS(COALESCE(PLAYER_DAMAGE_T.life_gain, 0)) AS life_gain + , ABS(COALESCE(PLAYER_DAMAGE_T.life_loss, 0)) AS life_loss + , COALESCE(PLAYER_DAMAGE_T.commander_deaths, 0) AS commander_deaths + , COALESCE(PLAYER_DAMAGE_T.is_eliminated, FALSE) AS is_eliminated + , COALESCE(PLAYER_DAMAGE_T.active, TRUE) AS active + , COALESCE(PLAYER_DAMAGE_T.created_on, v_time_start) AS created_on + , COALESCE(PLAYER_DAMAGE_T.created_by_user_id, v_user_id) AS created_by_user_id + , COALESCE(PLAYER_DAMAGE_T.updated_last_on, v_time_start) AS updated_last_on + , COALESCE(PLAYER_DAMAGE_T.updated_last_by_user_id, v_user_id) AS updated_last_by_user_id + FROM tcg.public.TCG_MTG_Game_Round_Player_Damage_Temp PLAYER_DAMAGE_T + LEFT JOIN tcg.public.TCG_MTG_Game_Round_Player_Damage PLAYER_DAMAGE + ON PLAYER_DAMAGE_T.damage_id = PLAYER_DAMAGE.damage_id + OR ( + COALESCE(PLAYER_DAMAGE_T.damage_id, 0) < 1 + AND PLAYER_DAMAGE_T.round_id = PLAYER_DAMAGE.round_id + AND PLAYER_DAMAGE_T.player_id = PLAYER_DAMAGE.player_id + AND ( + PLAYER_DAMAGE_T.received_from_commander_player_id = PLAYER_DAMAGE.received_from_commander_player_id + OR ( + PLAYER_DAMAGE_T.received_from_commander_player_id IS NULL + AND PLAYER_DAMAGE.received_from_commander_player_id IS NULL + ) + ) + ) + LEFT JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON PLAYER_DAMAGE_T.round_id = T_ROUND.round_id + WHERE PLAYER_DAMAGE_T.guid = v_guid + ) INSERT INTO Temp_MTG_Round_Damage_Save_Round_Player_Damage ( temp_id , damage_id @@ -192,62 +284,44 @@ BEGIN , error_name ) SELECT - PLAYER_DAMAGE_T.temp_id - , CASE WHEN COALESCE(PLAYER_DAMAGE_T.damage_id, 0) < 1 - THEN COALESCE(PLAYER_DAMAGE.damage_id, PLAYER_DAMAGE_T.damage_id, 0) - ELSE PLAYER_DAMAGE_T.damage_id - END -- damage_id - , T_ROUND.temp_id AS temp_round_id - , PLAYER_DAMAGE_T.round_id - , PLAYER_DAMAGE_T.player_id - , PLAYER_DAMAGE_T.received_from_commander_player_id - , ABS(COALESCE(PLAYER_DAMAGE_T.life_gain, 0)) -- life_gain - , ABS(COALESCE(PLAYER_DAMAGE_T.life_loss, 0)) -- life_loss - , COALESCE(PLAYER_DAMAGE_T.commander_deaths, 0) -- commander_deaths - , COALESCE(PLAYER_DAMAGE_T.is_eliminated, FALSE) -- is_eliminated - , COALESCE(PLAYER_DAMAGE_T.active, TRUE) -- active - , COALESCE(PLAYER_DAMAGE_T.created_on, v_time_start) -- created_on - , COALESCE(PLAYER_DAMAGE_T.created_by_user_id, a_user_id) -- created_by_user_id - , COALESCE(PLAYER_DAMAGE_T.updated_last_on, v_time_start) -- updated_last_on - , COALESCE(PLAYER_DAMAGE_T.updated_last_by_user_id, a_user_id) -- updated_last_by_user_id + T_PLAYER_DAMAGE.temp_id + , T_PLAYER_DAMAGE.damage_id + , T_PLAYER_DAMAGE.temp_round_id + , T_PLAYER_DAMAGE.round_id + , T_PLAYER_DAMAGE.player_id + , T_PLAYER_DAMAGE.received_from_commander_player_id + , T_PLAYER_DAMAGE.life_gain + , T_PLAYER_DAMAGE.life_loss + , T_PLAYER_DAMAGE.commander_deaths + , T_PLAYER_DAMAGE.is_eliminated + , T_PLAYER_DAMAGE.active + , T_PLAYER_DAMAGE.created_on + , T_PLAYER_DAMAGE.created_by_user_id + , T_PLAYER_DAMAGE.updated_last_on + , T_PLAYER_DAMAGE.updated_last_by_user_id , CASE WHEN PLAYER_DAMAGE.damage_id IS NULL THEN TRUE ELSE FALSE END AS is_new , CONCAT( 'Round Player Damage { id: ' - , CAST(PLAYER_DAMAGE_T.damage_id AS VARCHAR) + , CAST(T_PLAYER_DAMAGE.damage_id AS VARCHAR) , ', temp id: ' - , CAST(PLAYER_DAMAGE_T.temp_id AS VARCHAR) + , CAST(T_PLAYER_DAMAGE.temp_id AS VARCHAR) , ', round id: ' - , CAST(PLAYER_DAMAGE_T.round_id AS VARCHAR) + , CAST(T_PLAYER_DAMAGE.round_id AS VARCHAR) , ', player id: ' - , CAST(PLAYER_DAMAGE_T.player_id AS VARCHAR) + , CAST(T_PLAYER_DAMAGE.player_id AS VARCHAR) , ', received from commander player id: ' - , CAST(PLAYER_DAMAGE_T.received_from_commander_player_id AS VARCHAR) + , CAST(T_PLAYER_DAMAGE.received_from_commander_player_id AS VARCHAR) , ', life gain: ' - , CAST(PLAYER_DAMAGE_T.life_gain AS VARCHAR) + , CAST(T_PLAYER_DAMAGE.life_gain AS VARCHAR) , ', life loss: ' - , CAST(PLAYER_DAMAGE_T.life_loss AS VARCHAR) + , CAST(T_PLAYER_DAMAGE.life_loss AS VARCHAR) , ' }' - ) -- error_name - FROM tcg.public.TCG_MTG_Game_Round_Player_Damage_Temp PLAYER_DAMAGE_T - LEFT JOIN tcg.public.TCG_MTG_Game_Round_Player_Damage PLAYER_DAMAGE - ON PLAYER_DAMAGE_T.damage_id = PLAYER_DAMAGE.damage_id - OR ( - COALESCE(PLAYER_DAMAGE_T.damage_id, 0) < 1 - AND PLAYER_DAMAGE_T.round_id = PLAYER_DAMAGE.round_id - AND PLAYER_DAMAGE_T.player_id = PLAYER_DAMAGE.player_id - AND ( - PLAYER_DAMAGE_T.received_from_commander_player_id = PLAYER_DAMAGE.received_from_commander_player_id - OR ( - PLAYER_DAMAGE_T.received_from_commander_player_id IS NULL - AND PLAYER_DAMAGE.received_from_commander_player_id IS NULL - ) - ) - ) - LEFT JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON PLAYER_DAMAGE_T.round_id = T_ROUND.round_id - WHERE PLAYER_DAMAGE_T.guid = a_guid + ) AS error_name + FROM Temp_Player_Damage T_PLAYER_DAMAGE + LEFT JOIN tcg.public.TCG_MTG_Game_Round_Player_Damage PLAYER_DAMAGE ON T_PLAYER_DAMAGE.damage_id = PLAYER_DAMAGE.damage_id ; - + /* UPDATE Temp_MTG_Round_Damage_Save_Round T_ROUND SET round_id = COALESCE(TCG_ROUND.round_id, T_ROUND.round_id) FROM tcg.public.TCG_MTG_Game_Round TCG_ROUND @@ -286,7 +360,8 @@ BEGIN AND T_PLAYER_DAMAGE.temp_round_id = T_ROUND.temp_id AND COALESCE(T_PLAYER_DAMAGE.damage_id, 0) < 1 ; - + */ + INSERT INTO Temp_MTG_Round_Damage_Save_Game ( game_id , notes @@ -296,6 +371,7 @@ BEGIN , location_name , start_on , end_on + , starting_life , active , created_on , created_by_user_id @@ -312,6 +388,7 @@ BEGIN , GAME.location_name , GAME.start_on , GAME.end_on + , GAME.starting_life , GAME.active , GAME.created_on , GAME.created_by_user_id @@ -352,9 +429,12 @@ BEGIN , PLAYER.updated_last_by_user_id , PLAYER.change_set_id FROM tcg.public.TCG_MTG_Game_Player PLAYER - INNER JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE + /* + INNER JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE ON PLAYER.player_id = T_PLAYER_DAMAGE.player_id OR PLAYER.player_id = T_PLAYER_DAMAGE.received_from_commander_player_id + */ + INNER JOIN Temp_MTG_Round_Damage_Save_Game T_GAME ON PLAYER.game_id = T_GAME.game_id ; /* @@ -499,123 +579,6 @@ BEGIN ; END IF; - - /* - -- Testing TESTING - - WITH - Existing_Round AS ( - SELECT - TCG_ROUND.round_id - , TCG_ROUND.game_id - , TCG_ROUND.display_order - FROM tcg.public.TCG_MTG_Game_Round TCG_ROUND - LEFT JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON TCG_ROUND.round_id = T_ROUND.round_id - WHERE - TCG_ROUND.active - /* - AND NOT EXISTS ( - SELECT * - FROM Temp_MTG_Round_Damage_Save_Round T_ROUND - WHERE T_ROUND.round_id = TCG_ROUND.round_id - ) - */ - AND T_ROUND.temp_id IS NULL - ) - , All_Round AS ( - SELECT - T_ROUND.temp_id - , T_ROUND.round_id - , T_ROUND.game_id - , T_ROUND.display_order - , TRUE AS is_save_record - FROM Temp_MTG_Round_Damage_Save_Round T_ROUND - UNION - SELECT - NULL AS temp_id - , EXISTING_ROUND.round_id - , EXISTING_ROUND.game_id - , EXISTING_ROUND.display_order - , FALSE AS is_save_record - FROM Existing_Round EXISTING_ROUND - ) - , Unique_Game_Round AS ( - SELECT - ALL_ROUND.game_id - , ALL_ROUND.display_order - , COUNT(*) AS count_rounds - FROM All_Round ALL_ROUND - GROUP BY - ALL_ROUND.game_id - , ALL_ROUND.display_order - ) - INSERT INTO Temp_MTG_Round_Damage_Save_Error ( - error_type_id - , message - ) - SELECT - v_bad_data_error_type_id -- error_type_id - , CONCAT( - 'TEST: Existing rounds: ' - , STRING_AGG( - CONCAT( - '{ Round ID: ' - , CAST(EXISTING_ROUND.round_id AS VARCHAR) - , ', Game ID: ' - , CAST(EXISTING_ROUND.game_id AS VARCHAR) - , ', Display order: ' - , CAST(EXISTING_ROUND.display_order AS VARCHAR) - , ' }' - ) - , ', ' - ) - ) -- message - FROM Existing_Round EXISTING_ROUND - UNION - SELECT - v_bad_data_error_type_id -- error_type_id - , CONCAT( - 'TEST: All rounds: ' - -- , STRING_AGG(CONCAT(ALL_ROUND.temp_id, ' - ', ALL_ROUND.game_id, ' - ', ALL_ROUND.display_order), ', ') - , STRING_AGG( - CONCAT( - '{ Temp ID: ' - , CAST(ALL_ROUND.temp_id AS VARCHAR) - , ', Round ID: ' - , CAST(ALL_ROUND.round_id AS VARCHAR) - , ', Game ID: ' - , CAST(ALL_ROUND.game_id AS VARCHAR) - , ', Display order: ' - , CAST(ALL_ROUND.display_order AS VARCHAR) - , ' }' - ) - , ', ' - ) - ) -- message - FROM All_Round ALL_ROUND - UNION - SELECT - v_bad_data_error_type_id -- error_type_id - , CONCAT( - 'TEST: Unique rounds: ' - -- , STRING_AGG(CONCAT(UNIQUE_ROUND.game_id, ' - ', UNIQUE_ROUND.display_order, ' - ', UNIQUE_ROUND.count_rounds), ', ') - , STRING_AGG( - CONCAT( - '{ Game ID: ' - , CAST(UNIQUE_ROUND.game_id AS VARCHAR) - , ', Display order: ' - , CAST(UNIQUE_ROUND.display_order AS VARCHAR) - , ' Count: ' - , CAST(UNIQUE_ROUND.count_rounds AS VARCHAR) - , ' }' - ) - , ', ' - ) - ) -- message - FROM Unique_Game_Round UNIQUE_ROUND - ; - */ - -- Validate Damage -- Missing fields WITH Player_Damage_Missing_Field AS ( @@ -788,6 +751,488 @@ BEGIN ; END IF; + -- Get all missing rounds and damage records for games + INSERT INTO Temp_MTG_Round_Damage_Save_Round ( + temp_id + , round_id + , game_id + , notes + , display_order + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + + , is_new + , error_name + ) + SELECT + -TCG_ROUND.round_id + , TCG_ROUND.round_id + , TCG_ROUND.game_id + , TCG_ROUND.notes + , TCG_ROUND.display_order + , TCG_ROUND.active + , TCG_ROUND.created_on + , TCG_ROUND.created_by_user_id + , TCG_ROUND.updated_last_on + , TCG_ROUND.updated_last_by_user_id + + , FALSE AS is_new + , CONCAT( + 'Round { id: ' + , CAST(TCG_ROUND.round_id AS VARCHAR) + , ', temp id: ' + , CAST(NULL AS VARCHAR) + , ', display order: ' + , CAST(TCG_ROUND.display_order AS VARCHAR) + , ', game id: ' + , CAST(TCG_ROUND.game_id AS VARCHAR) + , ' }' + ) -- error_name + FROM tcg.public.TCG_MTG_Game_Round TCG_ROUND + INNER JOIN Temp_MTG_Round_Damage_Save_Game T_GAME ON TCG_ROUND.game_id = T_GAME.game_id + LEFT JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON TCG_ROUND.round_id = T_ROUND.round_id + WHERE T_ROUND.round_id IS NULL + ; + + INSERT INTO Temp_MTG_Round_Damage_Save_Round_Player_Damage ( + temp_id + , damage_id + , temp_round_id + , round_id + , player_id + , received_from_commander_player_id + , life_gain + , life_loss + , commander_deaths + , is_eliminated + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + + , is_new + , error_name + ) + SELECT + -PLAYER_DAMAGE.damage_id + , PLAYER_DAMAGE.damage_id + , T_ROUND.temp_id AS temp_round_id + , PLAYER_DAMAGE.round_id + , PLAYER_DAMAGE.player_id + , PLAYER_DAMAGE.received_from_commander_player_id + , PLAYER_DAMAGE.life_gain + , PLAYER_DAMAGE.life_loss + , PLAYER_DAMAGE.commander_deaths + , PLAYER_DAMAGE.is_eliminated + , PLAYER_DAMAGE.active + , PLAYER_DAMAGE.created_on + , PLAYER_DAMAGE.created_by_user_id + , PLAYER_DAMAGE.updated_last_on + , PLAYER_DAMAGE.updated_last_by_user_id + + , FALSE AS is_new + , CONCAT( + 'Round Player Damage { id: ' + , CAST(PLAYER_DAMAGE.damage_id AS VARCHAR) + , ', temp id: ' + , CAST(NULL AS VARCHAR) + , ', round id: ' + , CAST(PLAYER_DAMAGE.round_id AS VARCHAR) + , ', player id: ' + , CAST(PLAYER_DAMAGE.player_id AS VARCHAR) + , ', received from commander player id: ' + , CAST(PLAYER_DAMAGE.received_from_commander_player_id AS VARCHAR) + , ', life gain: ' + , CAST(PLAYER_DAMAGE.life_gain AS VARCHAR) + , ', life loss: ' + , CAST(PLAYER_DAMAGE.life_loss AS VARCHAR) + , ' }' + ) AS error_name + FROM tcg.public.TCG_MTG_Game_Round_Player_Damage PLAYER_DAMAGE + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON PLAYER_DAMAGE.round_id = T_ROUND.round_id + LEFT JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE ON PLAYER_DAMAGE.damage_id = T_PLAYER_DAMAGE.damage_id + WHERE T_PLAYER_DAMAGE.damage_id IS NULL + ; + + -- Calculations + WITH + Game_Length AS ( + SELECT + T_GAME.game_id + , MAX(T_ROUND.display_order) AS max_round_display_order + FROM Temp_MTG_Round_Damage_Save_Game T_GAME + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND + ON T_GAME.game_id = T_ROUND.game_id + AND T_ROUND.active + GROUP BY T_GAME.game_id + ) + , Game_Size AS ( + SELECT + T_GAME.game_id + , COUNT(*) AS count_players + FROM Temp_MTG_Round_Damage_Save_Game T_GAME + INNER JOIN Temp_MTG_Round_Damage_Save_Player T_PLAYER + ON T_GAME.game_id = T_PLAYER.game_id + AND T_PLAYER.active + GROUP BY T_GAME.game_id + ) + , Game_Combined AS ( + SELECT + T_GAME.game_id + , GAME_LENGTH.max_round_display_order + , GAME_SIZE.count_players + FROM Temp_MTG_Round_Damage_Save_Game T_GAME + LEFT JOIN Game_Length GAME_LENGTH ON T_GAME.game_id = GAME_LENGTH.game_id + LEFT JOIN Game_Size GAME_SIZE ON T_GAME.game_id = GAME_SIZE.game_id + ) + UPDATE Temp_MTG_Round_Damage_Save_Game T_GAME + SET + max_round_display_order = COALESCE(GAME_COMBINED.max_round_display_order, 0) + , count_players = COALESCE(GAME_COMBINED.count_players, 0) + , duration = CASE + WHEN + T_GAME.start_on IS NOT NULL + AND T_GAME.end_on IS NOT NULL + THEN T_GAME.end_on - T_GAME.start_on + ELSE NULL + END + FROM Game_Combined GAME_COMBINED + WHERE T_GAME.game_id = GAME_COMBINED.game_id + ; + + WITH + All_Player_Round AS ( + SELECT + T_ROUND.game_id + , T_PLAYER.player_id + , T_ROUND.round_id + FROM Temp_MTG_Round_Damage_Save_Round T_ROUND + -- INNER JOIN Temp_MTG_Round_Damage_Save_Game T_GAME ON T_ROUND.game_id = T_GAME.game_id + CROSS JOIN Temp_MTG_Round_Damage_Save_Player T_PLAYER -- ON T_ROUND.game_id = T_PLAYER.game_id + WHERE + T_ROUND.active + AND T_PLAYER.active + ) + , Player_Round_Commander_Damage_Received AS ( + SELECT + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + + , SUM(T_PLAYER_DAMAGE.life_loss) AS total_commander_damage_received + FROM All_Player_Round ALL_PLAYER_ROUND + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_PLAYER ON ALL_PLAYER_ROUND.round_id = T_ROUND_PLAYER.round_id + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_DAMAGE + ON T_ROUND_PLAYER.game_id = T_ROUND_DAMAGE.game_id + AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order + INNER JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE + ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.player_id + AND T_PLAYER_DAMAGE.received_from_commander_player_id IS NOT NULL + GROUP BY + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + -- , ALL_PLAYER_ROUND.received_from_commander_player_id + ) + , Player_Round_Max_Commander_Damage_Received AS ( + SELECT + PLAYER_ROUND_COMMANDER_DAMAGE_IN.game_id + , PLAYER_ROUND_COMMANDER_DAMAGE_IN.player_id + , PLAYER_ROUND_COMMANDER_DAMAGE_IN.round_id + + , MAX(PLAYER_ROUND_COMMANDER_DAMAGE_IN.total_commander_damage_received) AS max_total_commander_damage_received + FROM Player_Round_Commander_Damage_Received PLAYER_ROUND_COMMANDER_DAMAGE_IN + GROUP BY + PLAYER_ROUND_COMMANDER_DAMAGE_IN.game_id + , PLAYER_ROUND_COMMANDER_DAMAGE_IN.player_id + , PLAYER_ROUND_COMMANDER_DAMAGE_IN.round_id + ) + , Player_Round_Total_Commander_Damage_Dealt AS ( + SELECT + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + + , SUM(T_PLAYER_DAMAGE.life_loss) AS total_commander_damage_dealt + FROM All_Player_Round ALL_PLAYER_ROUND + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_PLAYER ON ALL_PLAYER_ROUND.round_id = T_ROUND_PLAYER.round_id + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_DAMAGE + -- ON ALL_PLAYER_ROUND.round_id = T_ROUND_DAMAGE.round_id + ON T_ROUND_PLAYER.game_id = T_ROUND_DAMAGE.game_id + AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order + INNER JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE + ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.received_from_commander_player_id + GROUP BY + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + ) + , Player_Round_Damage AS ( + SELECT + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + + , SUM(T_PLAYER_DAMAGE.life_loss) AS total_damage_received + FROM All_Player_Round ALL_PLAYER_ROUND + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_PLAYER ON ALL_PLAYER_ROUND.round_id = T_ROUND_PLAYER.round_id + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_DAMAGE + -- ON ALL_PLAYER_ROUND.round_id = T_ROUND_DAMAGE.round_id + ON T_ROUND_PLAYER.game_id = T_ROUND_DAMAGE.game_id + AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order + INNER JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE + ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.player_id + AND T_PLAYER_DAMAGE.life_loss > 0 + GROUP BY + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + ) + , Player_Round_Eliminated AS ( + SELECT + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + + , BOOL_OR(T_PLAYER_DAMAGE.is_eliminated) AS is_eliminated + , SUM(T_PLAYER_DAMAGE.commander_deaths) AS total_commander_deaths + FROM All_Player_Round ALL_PLAYER_ROUND + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_PLAYER ON ALL_PLAYER_ROUND.round_id = T_ROUND_PLAYER.round_id + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_DAMAGE + ON T_ROUND_PLAYER.game_id = T_ROUND_DAMAGE.game_id + AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order + INNER JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE + ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.player_id + GROUP BY + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + ) + , Player_Round_Total_Life AS ( + SELECT + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + + , SUM(T_PLAYER_DAMAGE.life_gain) AS total_life_gained + FROM All_Player_Round ALL_PLAYER_ROUND + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_PLAYER ON ALL_PLAYER_ROUND.round_id = T_ROUND_PLAYER.round_id + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_DAMAGE + -- ON ALL_PLAYER_ROUND.round_id = T_ROUND_DAMAGE.round_id + ON T_ROUND_PLAYER.game_id = T_ROUND_DAMAGE.game_id + AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order + INNER JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE + ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.player_id + AND T_PLAYER_DAMAGE.life_gain > 0 + GROUP BY + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + ) + INSERT INTO Temp_MTG_Round_Damage_Save_Player_Round_Link ( + game_id + , player_id + , round_id + + , max_total_commander_damage_received + , total_commander_damage_dealt + , total_damage_received + , is_eliminated + , total_commander_deaths + , total_life_gained + ) + SELECT + ALL_PLAYER_ROUND.game_id + , ALL_PLAYER_ROUND.player_id + , ALL_PLAYER_ROUND.round_id + + , COALESCE(PLAYER_ROUND_MAX_CDR_DAMAGE_IN.max_total_commander_damage_received, 0) AS max_total_commander_damage_received + , COALESCE(PLAYER_ROUND_TOTAL_CDR_DAMAGE_OUT.total_commander_damage_dealt, 0) AS total_commander_damage_dealt + , COALESCE(PLAYER_ROUND_TOTAL_DAMAGE.total_damage_received, 0) AS total_damage_received + , COALESCE(PLAYER_ROUND_ELIMINATED.is_eliminated, FALSE) AS is_eliminated + , COALESCE(PLAYER_ROUND_ELIMINATED.total_commander_deaths, 0) AS total_commander_deaths + , COALESCE(PLAYER_ROUND_TOTAL_LIFE.total_life_gained, 0) AS total_life_gained + FROM All_Player_Round ALL_PLAYER_ROUND + LEFT JOIN Player_Round_Max_Commander_Damage_Received PLAYER_ROUND_MAX_CDR_DAMAGE_IN + ON ALL_PLAYER_ROUND.round_id = PLAYER_ROUND_MAX_CDR_DAMAGE_IN.round_id + AND ALL_PLAYER_ROUND.player_id = PLAYER_ROUND_MAX_CDR_DAMAGE_IN.player_id + LEFT JOIN Player_Round_Total_Commander_Damage_Dealt PLAYER_ROUND_TOTAL_CDR_DAMAGE_OUT + ON ALL_PLAYER_ROUND.round_id = PLAYER_ROUND_TOTAL_CDR_DAMAGE_OUT.round_id + AND ALL_PLAYER_ROUND.player_id = PLAYER_ROUND_TOTAL_CDR_DAMAGE_OUT.player_id + LEFT JOIN Player_Round_Damage PLAYER_ROUND_TOTAL_DAMAGE + ON ALL_PLAYER_ROUND.round_id = PLAYER_ROUND_TOTAL_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = PLAYER_ROUND_TOTAL_DAMAGE.player_id + LEFT JOIN Player_Round_Eliminated PLAYER_ROUND_ELIMINATED + ON ALL_PLAYER_ROUND.round_id = PLAYER_ROUND_ELIMINATED.round_id + AND ALL_PLAYER_ROUND.player_id = PLAYER_ROUND_ELIMINATED.player_id + LEFT JOIN Player_Round_Total_Life PLAYER_ROUND_TOTAL_LIFE + ON ALL_PLAYER_ROUND.round_id = PLAYER_ROUND_TOTAL_LIFE.round_id + AND ALL_PLAYER_ROUND.player_id = PLAYER_ROUND_TOTAL_LIFE.player_id + ; + + WITH + Player_Round_Eliminated AS ( + SELECT + T_PLAYER_ROUND_LINK.player_id + , T_GAME.game_id + , T_GAME.max_round_display_order AS game_max_round_display_order + , MIN(T_ROUND.display_order) AS round_display_order + FROM Temp_MTG_Round_Damage_Save_Player_Round_Link T_PLAYER_ROUND_LINK + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON T_PLAYER_ROUND_LINK.round_id = T_ROUND.round_id + INNER JOIN Temp_MTG_Round_Damage_Save_Game T_GAME ON T_PLAYER_ROUND_LINK.game_id = T_GAME.game_id + WHERE + T_PLAYER_ROUND_LINK.max_total_commander_damage_received >= v_commander_damage_limit + OR T_PLAYER_ROUND_LINK.total_damage_received >= T_GAME.starting_life + T_PLAYER_ROUND_LINK.total_life_gained + OR T_PLAYER_ROUND_LINK.is_eliminated + GROUP BY + T_PLAYER_ROUND_LINK.player_id + , T_GAME.game_id + , T_GAME.max_round_display_order + ) + , Player_Round_Final AS ( + SELECT + PLAYER_ROUND_ELIMINATED.player_id + , PLAYER_ROUND_ELIMINATED.round_display_order AS round_display_order_eliminated + , COALESCE( + PLAYER_ROUND_ELIMINATED.round_display_order + , PLAYER_ROUND_ELIMINATED.game_max_round_display_order + ) AS final_player_damage_round_display_order + , T_ROUND_FINAL.round_id AS final_player_damage_round_id + , RANK() OVER ( + PARTITION BY PLAYER_ROUND_ELIMINATED.game_id + ORDER BY COALESCE( + PLAYER_ROUND_ELIMINATED.round_display_order + , PLAYER_ROUND_ELIMINATED.game_max_round_display_order + 1 + ) + ) AS placement + FROM Player_Round_Eliminated PLAYER_ROUND_ELIMINATED + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND_FINAL + ON COALESCE( + PLAYER_ROUND_ELIMINATED.round_display_order + , PLAYER_ROUND_ELIMINATED.game_max_round_display_order + 1 + ) = T_ROUND_FINAL.display_order + AND PLAYER_ROUND_ELIMINATED.game_id = T_ROUND_FINAL.game_id + AND T_ROUND_FINAL.active + ) + , Player_Final_Round_Aggregated AS ( + SELECT + PLAYER_ROUND_FINAL.player_id + , MAX(T_PLAYER_ROUND_LINK.max_total_commander_damage_received) AS max_total_commander_damage_received + , SUM(T_PLAYER_ROUND_LINK.total_commander_damage_dealt) AS total_commander_damage_dealt + , SUM(T_PLAYER_ROUND_LINK.total_damage_received) AS total_damage_received + , SUM(T_PLAYER_ROUND_LINK.total_commander_deaths) AS total_commander_deaths + , SUM(T_PLAYER_ROUND_LINK.total_life_gained) AS total_life_gained + FROM Player_Round_Final PLAYER_ROUND_FINAL -- Player_Round_Eliminated PLAYER_ROUND_ELIMINATED + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON PLAYER_ROUND_FINAL.final_player_damage_round_id = T_ROUND.round_id + INNER JOIN Temp_MTG_Round_Damage_Save_Player_Round_Link T_PLAYER_ROUND_LINK + ON PLAYER_ROUND_FINAL.player_id = T_PLAYER_ROUND_LINK.player_id + AND PLAYER_ROUND_FINAL.final_player_damage_round_id = T_PLAYER_ROUND_LINK.round_id + GROUP BY PLAYER_ROUND_FINAL.player_id + ) + UPDATE Temp_MTG_Round_Damage_Save_Player T_PLAYER + SET + round_display_order_eliminated = PLAYER_ROUND_FINAL.round_display_order_eliminated + , final_player_damage_round_id = PLAYER_ROUND_FINAL.final_player_damage_round_id + , placement = PLAYER_ROUND_FINAL.placement + , max_total_commander_damage_received = PLAYER_FINAL_ROUND_AGGREGATED.max_total_commander_damage_received + , total_commander_damage_dealt = PLAYER_FINAL_ROUND_AGGREGATED.total_commander_damage_dealt + , total_damage_received = PLAYER_FINAL_ROUND_AGGREGATED.total_damage_received + , total_life_gained = PLAYER_FINAL_ROUND_AGGREGATED.total_life_gained + /* + FROM Player_Placement PLAYER_PLACEMENT + INNER JOIN Player_Final_Round_Aggregated PLAYER_FINAL_ROUND_AGGREGATED ON PLAYER_PLACEMENT.player_id = PLAYER_FINAL_ROUND_AGGREGATED.player_id + WHERE T_PLAYER.player_id = PLAYER_PLACEMENT.player_id + */ + FROM Player_Round_Final PLAYER_ROUND_FINAL + INNER JOIN Player_Final_Round_Aggregated PLAYER_FINAL_ROUND_AGGREGATED ON PLAYER_ROUND_FINAL.player_id = PLAYER_FINAL_ROUND_AGGREGATED.player_id + WHERE T_PLAYER.player_id = PLAYER_ROUND_FINAL.player_id + ; + + WITH + Round_Survivor AS ( + SELECT + T_PLAYER_ROUND_LINK.round_id + , COUNT(*) AS count_survivors + FROM Temp_MTG_Round_Damage_Save_Player_Round_Link T_PLAYER_ROUND_LINK + INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON T_PLAYER_ROUND_LINK.round_id = T_ROUND.round_id + INNER JOIN Temp_MTG_Round_Damage_Save_Game T_GAME ON T_ROUND.game_id = T_GAME.game_id + WHERE + T_PLAYER_ROUND_LINK.max_total_commander_damage_received < v_commander_damage_limit + AND T_PLAYER_ROUND_LINK.total_damage_received < T_GAME.starting_life + T_PLAYER_ROUND_LINK.total_life_gained + AND NOT T_PLAYER_ROUND_LINK.is_eliminated + GROUP BY T_PLAYER_ROUND_LINK.round_id + ) + , All_Round_Survivor AS ( + SELECT + T_ROUND.round_id + , COALESCE(ROUND_SURVIVOR.count_survivors, 0) AS count_survivors + FROM Temp_MTG_Round_Damage_Save_Round T_ROUND + LEFT JOIN Round_Survivor ROUND_SURVIVOR ON T_ROUND.round_id = ROUND_SURVIVOR.round_id + ) + UPDATE Temp_MTG_Round_Damage_Save_Round T_ROUND + SET + count_survivors = ALL_ROUND_SURVIVOR.count_survivors + FROM All_Round_Survivor ALL_ROUND_SURVIVOR + WHERE T_ROUND.round_id = ALL_ROUND_SURVIVOR.round_id + ; + + UPDATE Temp_MTG_Round_Damage_Save_Game T_GAME + SET end_on = COALESCE(T_GAME.end_on, v_time_start) + FROM Temp_MTG_Round_Damage_Save_Round T_ROUND + WHERE + T_GAME.game_id = T_ROUND.game_id + AND T_ROUND.count_survivors <= 1 + AND T_ROUND.active + ; + + WITH + Game_Final_Round AS ( + SELECT + T_ROUND.game_id + , MIN(T_ROUND.display_order) AS final_round_display_order + FROM Temp_MTG_Round_Damage_Save_Round T_ROUND + WHERE + T_ROUND.count_survivors <= 1 + AND T_ROUND.active + GROUP BY T_ROUND.game_id + ) + , Game_Latest_Round AS ( + SELECT + GAME_FINAL_ROUND.game_id + , GAME_FINAL_ROUND.final_round_display_order + , TRUE AS Is_Completed + FROM Game_Final_Round GAME_FINAL_ROUND + UNION + SELECT + T_ROUND.game_id + , MAX(T_ROUND.display_order) AS final_round_display_order + , FALSE AS is_completed + FROM Temp_MTG_Round_Damage_Save_Round T_ROUND + LEFT JOIN Game_Final_Round GAME_FINAL_ROUND ON T_ROUND.game_id = GAME_FINAL_ROUND.game_id + WHERE + T_ROUND.count_survivors > 1 + AND GAME_FINAL_ROUND.game_id IS NULL + AND T_ROUND.active + GROUP BY T_ROUND.game_id + ) + UPDATE Temp_MTG_Round_Damage_Save_Game T_GAME + SET end_on = CASE WHEN GAME_LATEST_ROUND.is_completed + THEN COALESCE(T_GAME.end_on, v_time_start) + ELSE NULL + END + FROM Game_Latest_Round GAME_LATEST_ROUND + WHERE T_GAME.game_id = GAME_LATEST_ROUND.game_id + ; + -- Nothing to save IF ( NOT EXISTS (SELECT * FROM Temp_MTG_Round_Damage_Save_Round LIMIT 1) @@ -803,6 +1248,80 @@ BEGIN ); END IF; + /* + INSERT INTO Temp_MTG_Round_Damage_Save_Error ( + error_type_id + , message + ) + SELECT + v_warning_error_type_id AS error_type_id + , CONCAT( + 'Games: ' + , STRING_AGG(CONCAT( + 'Id: ' + , CAST(T_GAME.game_id AS TEXT) + , ', End: ' + , CAST(T_GAME.end_on AS TEXT) + ), ', ') + ) AS message + FROM Temp_MTG_Round_Damage_Save_Game T_GAME + UNION + VALUES ( + v_warning_error_type_id -- AS error_type_id + , CONCAT( + 'Count games: ' + , (SELECT COUNT(*) FROM Temp_MTG_Round_Damage_Save_Game T_GAME) + ) -- AS message + ) + UNION + SELECT + v_warning_error_type_id AS error_type_id + , CONCAT( + 'Rounds: ' + , STRING_AGG(CONCAT( + '{ Id: ' + , CAST(T_ROUND.round_id AS TEXT) + , ', Display order: ' + , CAST(T_ROUND.display_order AS TEXT) + , ', Survivors: ' + , CAST(T_ROUND.count_survivors AS TEXT) + , '}' + ), ', ') + ) AS message + FROM Temp_MTG_Round_Damage_Save_Round T_ROUND + UNION + SELECT + v_warning_error_type_id AS error_type_id + , CONCAT( + 'Round Player Links: ' + , STRING_AGG(CONCAT( + ' Round Player Link: { ' + , 'game_id: ' + , game_id::TEXT + , ', player id: ' + , player_id::TEXT + , ', round id: ' + , round_id::TEXT + + , ', max_total_commander_damage_received: ' + , max_total_commander_damage_received::TEXT + , ', total_commander_damage_dealt: ' + , total_commander_damage_dealt::TEXT + , ', total_damage_received: ' + , total_damage_received::TEXT + , ', is_eliminated: ' + , is_eliminated::TEXT + , ', total_commander_deaths: ' + , total_commander_deaths::TEXT + , ', total_life_gained: ' + , total_life_gained::TEXT + , ' }' + ), ', ') + ) + FROM Temp_MTG_Round_Damage_Save_Player_Round_Link T_PLAYER_ROUND + ; + */ + -- Outputs /* INSERT INTO Temp_MTG_Round_Damage_Save_Error ( @@ -860,14 +1379,53 @@ BEGIN , updated_last_by_user_id ) VALUES ( - a_comment - , a_user_id + v_comment + , v_user_id ) RETURNING change_set_id INTO v_change_set_id ; + + -- Error + INSERT INTO tcg.public.Error ( + guid + , error_type_id + , message + , display_order + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT + v_guid + , T_ERROR.error_type_id + , T_ERROR.message + , T_ERROR.temp_id + , v_time_start + , v_user_id + , v_time_start + , v_user_id + , v_change_set_id + FROM Temp_MTG_Round_Damage_Save_Error T_ERROR + LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON T_ERROR.error_type_id = ERROR_TYPE.error_type_id + ORDER BY T_ERROR.temp_id + ; IF NOT EXISTS (SELECT * FROM Temp_MTG_Round_Damage_Save_Error T_ERROR WHERE T_ERROR.error_type_id <> v_warning_error_type_id LIMIT 1) THEN + -- Set game updated last on + UPDATE tcg.public.TCG_MTG_Game TCG_GAME + SET + end_on = T_GAME.end_on + , updated_last_on = v_time_start + , updated_last_by_user_id = v_user_id + , change_set_id = v_change_set_id + FROM Temp_MTG_Round_Damage_Save_Game T_GAME + -- Temp_MTG_Round_Damage_Save_Round T_ROUND + WHERE TCG_GAME.game_id = T_GAME.game_id + ; + -- Round INSERT INTO tcg.public.TCG_MTG_Game_Round ( game_id @@ -886,9 +1444,9 @@ BEGIN , T_ROUND.display_order , T_ROUND.active , v_time_start -- created_on - , a_user_id -- created_by_user_id + , v_user_id -- created_by_user_id , v_time_start -- updated_last_on - , a_user_id -- updated_last_by_user_id + , v_user_id -- updated_last_by_user_id , v_change_set_id -- change_set_id FROM Temp_MTG_Round_Damage_Save_Round T_ROUND LEFT JOIN Temp_MTG_Round_Damage_Save_Game T_GAME ON T_ROUND.game_id = T_GAME.game_id @@ -907,7 +1465,7 @@ BEGIN , display_order = T_ROUND.display_order , active = T_ROUND.active , updated_last_on = v_time_start - , updated_last_by_user_id = a_user_id + , updated_last_by_user_id = v_user_id , change_set_id = v_change_set_id FROM Temp_MTG_Round_Damage_Save_Round T_ROUND WHERE @@ -950,9 +1508,9 @@ BEGIN , T_PLAYER_DAMAGE.is_eliminated , T_PLAYER_DAMAGE.active , v_time_start -- created_on - , a_user_id -- created_by_user_id + , v_user_id -- created_by_user_id , v_time_start -- updated_last_on - , a_user_id -- updated_last_by_user_id + , v_user_id -- updated_last_by_user_id , v_change_set_id -- change_set_id FROM Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON T_PLAYER_DAMAGE.temp_round_id = T_ROUND.temp_id @@ -978,7 +1536,7 @@ BEGIN , is_eliminated = T_PLAYER_DAMAGE.is_eliminated , active = T_PLAYER_DAMAGE.active , updated_last_on = v_time_start - , updated_last_by_user_id = a_user_id + , updated_last_by_user_id = v_user_id , change_set_id = v_change_set_id FROM Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE INNER JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON T_PLAYER_DAMAGE.temp_round_id = T_ROUND.temp_id @@ -986,33 +1544,6 @@ BEGIN PLAYER_DAMAGE.damage_id = T_PLAYER_DAMAGE.damage_id AND NOT T_PLAYER_DAMAGE.is_new ; - ELSE - -- Error - INSERT INTO tcg.public.Error ( - guid - , error_type_id - , message - , display_order - , created_on - , created_by_user_id - , updated_last_on - , updated_last_by_user_id - , change_set_id - ) - SELECT - a_guid - , T_ERROR.error_type_id - , T_ERROR.message - , T_ERROR.temp_id - , v_time_start - , a_user_id - , v_time_start - , a_user_id - , v_change_set_id - FROM Temp_MTG_Round_Damage_Save_Error T_ERROR - LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON T_ERROR.error_type_id = ERROR_TYPE.error_type_id - ORDER BY T_ERROR.temp_id - ; END IF; COMMIT; @@ -1024,8 +1555,8 @@ BEGIN LIMIT 1 ); - DELETE FROM tcg.public.TCG_MTG_Game_Round_Temp ROUND_T WHERE ROUND_T.guid = a_guid; - DELETE FROM tcg.public.TCG_MTG_Game_Round_Player_Damage_Temp ROUND_DAMAGE_T WHERE ROUND_DAMAGE_T.guid = a_guid; + -- DELETE FROM tcg.public.TCG_MTG_Game_Round_Temp ROUND_T WHERE ROUND_T.guid = v_guid; + -- DELETE FROM tcg.public.TCG_MTG_Game_Round_Player_Damage_Temp ROUND_DAMAGE_T WHERE ROUND_DAMAGE_T.guid = v_guid; DROP TABLE IF EXISTS Temp_MTG_Round_Damage_Save_Game; DROP TABLE IF EXISTS Temp_MTG_Round_Damage_Save_Player; @@ -1043,8 +1574,77 @@ DECLARE v_user_id INT := 3; v_success BOOLEAN; BEGIN - v_guid := '6307bed6-73a1-41ab-9a90-79e18e14dd81'::UUID; -- gen_random_uuid(); + v_guid := '3935de65-d9a6-401b-9c6a-79f99e8d0642'::UUID; -- gen_random_uuid(); -- '6307bed6-73a1-41ab-9a90-79e18e14dd81'::UUID; +/* + INSERT INTO tcg.public.TCG_MTG_Game_Round_Temp ( + guid + , round_id + , game_id + , notes + , display_order + , active + ) + VALUES ( + v_guid -- guid + , -1 -- round_id + , 4 -- game_id + , 'Beaten' -- notes + , 5 -- display_order + , TRUE -- active + ) + ; + INSERT INTO tcg.public.TCG_MTG_Game_Round_Player_Damage_Temp ( + guid + , damage_id + , round_id + , player_id + , received_from_commander_player_id + -- , health_change + , life_gain + , life_loss + , commander_deaths + , active + ) + VALUES + ( + v_guid -- guid + , NULL -- damage_id + , -1 -- round_id + , 3 -- player_id + , NULL -- received_from_commander_player_id + -- , -4 -- health_change + , 0 -- life_gain + , 4 -- life_loss + , 1 -- commander_deaths + , TRUE -- active + ) + , ( + v_guid -- guid + , NULL -- damage_id + , -1 -- round_id + , 3 -- player_id + , 2 -- received_from_commander_player_id + -- , -5 -- health_change + , 0 -- life_gain + , 5 -- life_loss + , NULL -- commander_deaths + , TRUE -- active + ) + , ( + v_guid -- guid + , NULL -- damage_id + , -1 -- round_id + , 3 -- player_id + , 5 -- received_from_commander_player_id + -- , -6 -- health_change + , 0 -- life_gain + , 6 -- life_loss + , NULL -- commander_deaths + , TRUE -- active + ) + ; +*/ CALL tcg.public.USP_TCG_MTG_Game_Round_Damage_Save ( a_comment := v_comment -- a_comment , a_guid := v_guid -- a_guid @@ -1091,8 +1691,16 @@ SELECT * FROM tcg.public.TCG_MTG_Game_Round_Player_Damage PLAYER_DAMAGE LEFT JOIN tcg.public.TCG_MTG_Game_Round TCG_ROUND ON PLAYER_DAMAGE.round_id = TCG_ROUND.round_id LEFT JOIN tcg.public.TCG_MTG_Game GAME ON TCG_ROUND.game_id = GAME.game_id +ORDER BY + GAME.game_id DESC + , TCG_ROUND.display_order + , PLAYER_DAMAGE.player_id + , PLAYER_DAMAGE.received_from_commander_player_id +; +SELECT * +FROM tcg.public.TCG_MTG_Game GAME +ORDER BY GAME.game_id DESC ; - /* @@ -1166,6 +1774,8 @@ LEFT JOIN tcg.public.TCG_MTG_Game GAME ON TCG_ROUND.game_id = GAME.game_id ; */ - +SELECT +FROM tcg.public.TCG_MTG_Game_Player PLAYER +WHERE PLAYER.game_id = 35 diff --git a/static/PostgreSQL/71224_fn_TCG_MTG_Game_Get_Many_Session_Member.sql b/static/PostgreSQL/71224_fn_TCG_MTG_Game_Get_Many_Session_Member.sql new file mode 100644 index 0000000..221bb80 --- /dev/null +++ b/static/PostgreSQL/71224_fn_TCG_MTG_Game_Get_Many_Session_Member.sql @@ -0,0 +1,140 @@ + +CREATE OR REPLACE FUNCTION tcg.public.FN_TCG_MTG_Game_Session_Member_Get_Many ( + a_get_inactive_session_member BOOLEAN + , a_get_all_game BOOLEAN + , a_get_inactive_game BOOLEAN + , a_game_ids TEXT + , a_get_all_user BOOLEAN + , a_get_inactive_user BOOLEAN + , a_user_ids TEXT + , a_require_all_id_filters_met BOOLEAN + , a_require_any_id_filters_met BOOLEAN +) +RETURNS TABLE ( + member_id INT + , game_id INT + , user_id INT + , is_permitted BOOLEAN + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT +) +LANGUAGE plpgsql +AS $$ +DECLARE + v_get_inactive_session_member BOOLEAN; + v_get_all_game BOOLEAN; + v_get_inactive_game BOOLEAN; + v_game_ids TEXT; + v_get_all_user BOOLEAN; + v_get_inactive_user BOOLEAN; + v_user_ids TEXT; + v_require_all_id_filters_met BOOLEAN; + v_require_any_id_filters_met BOOLEAN; + -- , v_require_all_non_id_filters_met BOOLEAN + -- , v_require_any_non_id_filters_met BOOLEAN +BEGIN + v_get_inactive_session_member := COALESCE(a_get_inactive_session_member, FALSE); + v_get_all_game := COALESCE(a_get_all_game, FALSE); + v_get_inactive_game := COALESCE(a_get_inactive_game, FALSE); + v_game_ids := TRIM(COALESCE(a_game_ids, '')); + v_get_all_user := COALESCE(a_get_all_user, FALSE); + v_get_inactive_user := COALESCE(a_get_inactive_user, FALSE); + v_user_ids := TRIM(COALESCE(a_user_ids, '')); + v_require_all_id_filters_met := COALESCE(a_require_all_id_filters_met, FALSE); + v_require_any_id_filters_met := COALESCE(a_require_any_id_filters_met, FALSE); + + -- Outputs + RETURN QUERY SELECT + SESSION_MEMBER.member_id + , SESSION_MEMBER.game_id + , SESSION_MEMBER.user_id + , SESSION_MEMBER.is_permitted + , SESSION_MEMBER.active + , SESSION_MEMBER.created_on + , SESSION_MEMBER.created_by_user_id + , SESSION_MEMBER.updated_last_on + , SESSION_MEMBER.updated_last_by_user_id + FROM tcg.public.TCG_MTG_Game_Session_Member SESSION_MEMBER + INNER JOIN tcg.public.TCG_MTG_Game GAME ON SESSION_MEMBER.game_id = GAME.game_id + INNER JOIN tcg.public.TCG_User MEMBER_USER ON SESSION_MEMBER.user_id = MEMBER_USER.user_id + WHERE + ( + ( + NOT v_require_all_id_filters_met + AND NOT v_require_any_id_filters_met + ) + OR ( + v_require_all_id_filters_met + AND ( + v_get_all_game + OR SESSION_MEMBER.game_id = ANY(string_to_array(v_game_ids, ',')::INT[]) + ) + AND ( + a_get_all_user + OR MEMBER_USER.user_id = ANY(string_to_array(v_user_ids, ',')::INT[]) + ) + ) + OR ( + NOT v_require_all_id_filters_met + AND v_require_any_id_filters_met + AND ( + v_get_all_game + OR SESSION_MEMBER.game_id = ANY(string_to_array(v_game_ids, ',')::INT[]) + ) + AND ( + v_get_all_user + OR MEMBER_USER.user_id = ANY(string_to_array(v_user_ids, ',')::INT[]) + ) + ) + ) + AND ( + v_get_inactive_session_member + OR SESSION_MEMBER.active + ) + AND ( + v_get_inactive_game + OR GAME.active + ) + AND ( + v_get_inactive_user + OR MEMBER_USER.active + ) + ORDER BY + GAME.game_id + , MEMBER_USER.firstname + , MEMBER_USER.surname + ; +END; +$$; + + +SELECT * +FROM tcg.public.FN_TCG_MTG_Game_Session_Member_Get_Many ( + a_get_inactive_session_member := FALSE + , a_get_all_game := TRUE + , a_get_inactive_game := FALSE + , a_game_ids := '' + , a_get_all_user := TRUE + , a_get_inactive_user := FALSE + , a_user_ids := '' + , a_require_all_id_filters_met := TRUE + , a_require_any_id_filters_met := FALSE +) +; + +/* +SELECT * +FROM tcg.public.TCG_MTG_Game_Session_Member +; + +SELECT * +FROM tcg.public.TCG_User +; + +SELECT * +FROM tcg.public.TCG_MTG_Deck +; +*/ diff --git a/static/PostgreSQL/71225_usp_TCG_MTG_Game_Session_Member_Save.sql b/static/PostgreSQL/71225_usp_TCG_MTG_Game_Session_Member_Save.sql new file mode 100644 index 0000000..f6bd48b --- /dev/null +++ b/static/PostgreSQL/71225_usp_TCG_MTG_Game_Session_Member_Save.sql @@ -0,0 +1,532 @@ + +CREATE OR REPLACE PROCEDURE tcg.public.USP_TCG_MTG_Game_Session_Member_Save ( + a_comment TEXT + , a_guid UUID + , a_user_id INT + , OUT o_success BOOLEAN +) +LANGUAGE plpgsql +AS $$ +DECLARE + v_bad_data_error_type_id INT; + v_change_set_id INT; + -- v_error_message TEXT; + v_time_start TIMESTAMP; + v_warning_error_type_id INT; +BEGIN + v_bad_data_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'BAD_DATA' LIMIT 1); + v_warning_error_type_id := (SELECT ERROR_TYPE.error_type_id FROM tcg.public.Error_Type ERROR_TYPE WHERE ERROR_TYPE.code = 'WARNING' LIMIT 1); + v_time_start := CURRENT_TIMESTAMP; + + DROP TABLE IF EXISTS Temp_User_Relationship_Save_Game; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_User; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_Session_Member; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_Error; + + CREATE TEMP TABLE Temp_User_Relationship_Save_Game ( + game_id INT NOT NULL + , notes TEXT + , is_commander BOOLEAN + , is_draft BOOLEAN + , is_sealed BOOLEAN + , location_name TEXT + , start_on TIMESTAMP + , end_on TIMESTAMP + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT + , change_set_id INT + ); + + CREATE TEMP TABLE Temp_User_Relationship_Save_User ( + user_id INT NOT NULL + , user_auth0_id TEXT + , firstname TEXT + , surname TEXT + , email TEXT + , is_email_verified BOOLEAN + , is_super_user BOOLEAN + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT + , change_set_id INT + ); + + CREATE TEMP TABLE Temp_User_Relationship_Save_Session_Member ( + temp_id INT NOT NULL + , member_id INT + , game_id INT + , user_id INT + , is_permitted BOOLEAN + , active BOOLEAN + , created_on TIMESTAMP + , created_by_user_id INT + , updated_last_on TIMESTAMP + , updated_last_by_user_id INT + + , is_new BOOLEAN + , error_name TEXT + , is_duplicate BOOLEAN + ); + + CREATE TEMP TABLE Temp_User_Relationship_Save_Error ( + temp_id INT GENERATED ALWAYS AS IDENTITY + , error_type_id INT + , message TEXT + ); + + INSERT INTO Temp_User_Relationship_Save_Session_Member ( + temp_id + , member_id + , game_id + , user_id + , is_permitted + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + + , is_new + , error_name + ) + SELECT + SESSION_MEMBER_T.temp_id + , SESSION_MEMBER_T.member_id + , SESSION_MEMBER_T.game_id + , SESSION_MEMBER_T.user_id + , COALESCE(SESSION_MEMBER_T.is_permitted, FALSE) -- is_permitted + , COALESCE(SESSION_MEMBER_T.active, TRUE) -- active + , COALESCE(SESSION_MEMBER_T.created_on, v_time_start) -- created_on + , COALESCE(SESSION_MEMBER_T.created_by_user_id, a_user_id) -- created_by_user_id + , COALESCE(SESSION_MEMBER_T.updated_last_on, v_time_start) -- updated_last_on + , COALESCE(SESSION_MEMBER_T.updated_last_by_user_id, a_user_id) -- updated_last_by_user_id + + , CASE WHEN SESSION_MEMBER .member_id IS NULL THEN TRUE ELSE FALSE END AS is_new + , CONCAT( + 'Member { id: ' + , CAST(SESSION_MEMBER_T.member_id AS VARCHAR) + , ', temp id: ' + , CAST(SESSION_MEMBER_T.temp_id AS VARCHAR) + , ', game id: ' + , CAST(SESSION_MEMBER_T.game_id AS VARCHAR) + , ', user id: ' + , CAST(SESSION_MEMBER_T.user_id AS VARCHAR) + , ' }' + ) -- error_name + FROM tcg.public.TCG_MTG_Game_Session_Member_Temp SESSION_MEMBER_T + LEFT JOIN tcg.public.TCG_MTG_Game_Session_Member SESSION_MEMBER ON SESSION_MEMBER_T.member_id = SESSION_MEMBER.member_id + WHERE SESSION_MEMBER_T.guid = a_guid + ; + + INSERT INTO Temp_User_Relationship_Save_Game ( + game_id + , notes + , is_commander + , is_draft + , is_sealed + , location_name + , start_on + , end_on + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT DISTINCT + GAME.game_id + , GAME.notes + , GAME.is_commander + , GAME.is_draft + , GAME.is_sealed + , GAME.location_name + , GAME.start_on + , GAME.end_on + , GAME.active + , GAME.created_on + , GAME.created_by_user_id + , GAME.updated_last_on + , GAME.updated_last_by_user_id + , GAME.change_set_id + FROM tcg.public.TCG_MTG_Game GAME + INNER JOIN Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T ON GAME.game_id = SESSION_MEMBER_T.game_id + ; + + INSERT INTO Temp_User_Relationship_Save_User ( + user_id + , user_auth0_id + , firstname + , surname + , email + , is_email_verified + , is_super_user + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT DISTINCT + TCG_USER.user_id + , TCG_USER.user_auth0_id + , TCG_USER.firstname + , TCG_USER.surname + , TCG_USER.email + , TCG_USER.is_email_verified + , TCG_USER.is_super_user + , TCG_USER.active + , TCG_USER.created_on + , TCG_USER.created_by_user_id + , TCG_USER.updated_last_on + , TCG_USER.updated_last_by_user_id + , TCG_USER.change_set_id + FROM tcg.public.TCG_User TCG_USER + INNER JOIN Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T ON TCG_USER.user_id = SESSION_MEMBER_T.user_id + ; + + -- Missing fields + WITH Session_Member_Missing_Field AS ( + SELECT + SESSION_MEMBER_T.temp_id + , 'game_id' AS field + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + WHERE SESSION_MEMBER_T.game_id IS NULL + UNION + SELECT + SESSION_MEMBER_T.temp_id + , 'user_id' AS field + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + WHERE SESSION_MEMBER_T.user_id IS NULL + ) + INSERT INTO Temp_User_Relationship_Save_Error ( + error_type_id + , message + ) + SELECT + v_bad_data_error_type_id -- error_type_id + , CONCAT( + 'Missing mandatory field: ' + , SESSION_MEMBER_MISSING_FIELD.field + , ' on ' + , SESSION_MEMBER_T.error_name + , '.' + ) -- message + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + INNER JOIN Session_Member_Missing_Field SESSION_MEMBER_MISSING_FIELD ON SESSION_MEMBER_T.temp_id = SESSION_MEMBER_MISSING_FIELD.temp_id + ; + + -- Failed join fields + WITH Session_Member_Failed_Join_Field AS ( + SELECT + SESSION_MEMBER_T.temp_id + , 'game_id' AS field + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + LEFT JOIN Temp_User_Relationship_Save_Game T_GAME ON SESSION_MEMBER_T.game_id = T_GAME.game_id + WHERE T_GAME.game_id IS NULL + UNION + SELECT + SESSION_MEMBER_T.temp_id + , 'user_id' AS field + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + LEFT JOIN Temp_User_Relationship_Save_User T_USER ON SESSION_MEMBER_T.user_id = T_USER.user_id + WHERE T_USER.user_id IS NULL + ) + INSERT INTO Temp_User_Relationship_Save_Error ( + error_type_id + , message + ) + SELECT + v_bad_data_error_type_id -- error_type_id + , CONCAT( + 'Failed relationship: ' + , SESSION_MEMBER_FAILED_JOIN_FIELD.field + , ' on ' + , SESSION_MEMBER_T.error_name + , '.' + ) -- message + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + INNER JOIN Session_Member_Failed_Join_Field SESSION_MEMBER_FAILED_JOIN_FIELD ON SESSION_MEMBER_T.temp_id = SESSION_MEMBER_FAILED_JOIN_FIELD.temp_id + ; + + -- Duplicate Session Member + -- By game and user + WITH + All_Session_Member AS ( + SELECT + SESSION_MEMBER_T.temp_id + , SESSION_MEMBER_T.game_id + , SESSION_MEMBER_T.user_id + , TRUE AS is_save_record + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + UNION + SELECT + NULL AS temp_id + , SESSION_MEMBER.game_id + , SESSION_MEMBER.user_id + , FALSE AS is_save_record + FROM tcg.public.TCG_MTG_Game_Session_Member SESSION_MEMBER + LEFT JOIN Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T ON SESSION_MEMBER.member_id = SESSION_MEMBER_T.member_id + WHERE + SESSION_MEMBER_T.member_id IS NULL + AND SESSION_MEMBER.active + ) + , Session_Member_Count AS ( + SELECT + ALL_SESSION_MEMBER.game_id + , ALL_SESSION_MEMBER.user_id + , COUNT(*) AS count_members + FROM All_Session_Member ALL_SESSION_MEMBER + GROUP BY + ALL_SESSION_MEMBER.game_id + , ALL_SESSION_MEMBER.user_id + ) + , Duplicate_Session_Member AS ( + SELECT + ALL_SESSION_MEMBER.temp_id + , ALL_SESSION_MEMBER.game_id + , ALL_SESSION_MEMBER.user_id + , CASE WHEN SESSION_MEMBER_COUNT.count_members = 1 THEN TRUE ELSE FALSE END AS is_unique_member + FROM All_Session_Member ALL_SESSION_MEMBER + INNER JOIN Session_Member_Count SESSION_MEMBER_COUNT + ON ALL_SESSION_MEMBER.game_id = SESSION_MEMBER_COUNT.game_id + AND ALL_SESSION_MEMBER.user_id = SESSION_MEMBER_COUNT.user_id + ) + UPDATE Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + SET is_duplicate = CASE WHEN NOT DUPLICATE_SESSION_MEMBER.is_unique_member THEN TRUE ELSE FALSE END + FROM Duplicate_Session_Member DUPLICATE_SESSION_MEMBER + WHERE SESSION_MEMBER_T.temp_id = DUPLICATE_SESSION_MEMBER.temp_id + ; + + IF EXISTS ( + SELECT * + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + WHERE SESSION_MEMBER_T.is_duplicate + LIMIT 1 + ) THEN + INSERT INTO Temp_User_Relationship_Save_Error ( + error_type_id + , message + ) + SELECT + v_bad_data_error_type_id -- error_type_id + , CONCAT( + 'Duplicate on ' + , SESSION_MEMBER_T.error_name + ) -- message + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + WHERE SESSION_MEMBER_T.is_duplicate + ; + END IF; + + -- Nothing to save + IF NOT EXISTS (SELECT * FROM Temp_User_Relationship_Save_Session_Member LIMIT 1) THEN + INSERT INTO Temp_User_Relationship_Save_Error ( + error_type_id + , message + ) + VALUES ( + v_warning_error_type_id + , 'Nothing to save.' + ); + END IF; + + -- Outputs + -- Change Set + INSERT INTO tcg.public.TCG_Change_Set ( + comment + , updated_last_by_user_id + ) + VALUES ( + a_comment + , a_user_id + ) + RETURNING change_set_id INTO v_change_set_id + ; + + IF NOT EXISTS (SELECT * FROM Temp_User_Relationship_Save_Error T_ERROR WHERE T_ERROR.error_type_id <> v_warning_error_type_id LIMIT 1) THEN + + -- Session Member + INSERT INTO tcg.public.TCG_MTG_Game_Session_Member ( + game_id + , user_id + , is_permitted + , active + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT + SESSION_MEMBER_T.game_id + , SESSION_MEMBER_T.user_id + , SESSION_MEMBER_T.is_permitted + , SESSION_MEMBER_T.active + , v_time_start -- created_on + , a_user_id -- created_by_user_id + , v_time_start -- updated_last_on + , a_user_id -- updated_last_by_user_id + , v_change_set_id -- change_set_id + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + LEFT JOIN Temp_User_Relationship_Save_Game T_GAME ON SESSION_MEMBER_T.game_id = T_GAME.game_id + WHERE + SESSION_MEMBER_T.is_new = TRUE + AND SESSION_MEMBER_T.active = TRUE + ORDER BY + T_GAME.created_on + , T_GAME.game_id + , SESSION_MEMBER_T.is_permitted + , SESSION_MEMBER_T.user_id + ; + + UPDATE tcg.public.TCG_MTG_Game_Session_Member SESSION_MEMBER + SET + game_id = SESSION_MEMBER_T.game_id + , user_id = SESSION_MEMBER_T.user_id + , is_permitted = SESSION_MEMBER_T.is_permitted + , active = SESSION_MEMBER_T.active + , updated_last_on = v_time_start + , updated_last_by_user_id = a_user_id + , change_set_id = v_change_set_id + FROM Temp_User_Relationship_Save_Session_Member SESSION_MEMBER_T + WHERE + SESSION_MEMBER.member_id = SESSION_MEMBER_T.member_id + AND NOT SESSION_MEMBER_T.is_new + ; + END IF; + + -- Error + INSERT INTO tcg.public.Error ( + guid + , error_type_id + , message + , display_order + , created_on + , created_by_user_id + , updated_last_on + , updated_last_by_user_id + , change_set_id + ) + SELECT + a_guid + , T_ERROR.error_type_id + , T_ERROR.message + , T_ERROR.temp_id + , v_time_start + , a_user_id + , v_time_start + , a_user_id + , v_change_set_id + FROM Temp_User_Relationship_Save_Error T_ERROR + LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON T_ERROR.error_type_id = ERROR_TYPE.error_type_id + ORDER BY T_ERROR.temp_id + ; + + COMMIT; + + o_success := NOT EXISTS ( + SELECT * + FROM Temp_User_Relationship_Save_Error T_ERROR + WHERE T_ERROR.error_type_id <> v_warning_error_type_id + LIMIT 1 + ); + + DELETE FROM tcg.public.TCG_MTG_Game_Session_Member_Temp SESSION_MEMBER_T WHERE SESSION_MEMBER_T.guid = a_guid; + + DROP TABLE IF EXISTS Temp_User_Relationship_Save_Game; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_User; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_Session_Member; + DROP TABLE IF EXISTS Temp_User_Relationship_Save_Error; +END; +$$; + + +-- Call it with: +DO $$ +DECLARE + v_comment TEXT := 'MTG Game Session Member Save.'; + v_guid UUID; + v_user_id INT := 3; + v_success BOOLEAN; +BEGIN + v_guid := gen_random_uuid(); + + INSERT INTO tcg.public.TCG_MTG_Game_Session_Member_Temp ( + guid + , member_id + , game_id + , user_id + , is_permitted + , active + ) + VALUES + ( + v_guid + , NULL -- member_id + , 4 -- game_id + , 3 -- user_id + , TRUE -- is_permitted + , TRUE -- active + ) + , ( + v_guid + , NULL -- member_id + , 4 -- game_id + , 4 -- user_id + , FALSE -- is_permitted + , TRUE -- active + ) + /* + , ( + v_guid + , NULL -- member_id + , 4 -- game_id + , 3 -- user_id + , FALSE -- is_permitted + , TRUE -- active + ) + */ + ; + + CALL tcg.public.USP_TCG_MTG_Game_Session_Member_Save ( + v_comment -- a_comment + , v_guid -- a_guid + , v_user_id -- a_user_id + , v_success -- o_success + ); + RAISE NOTICE 'Success: %', CASE WHEN v_success THEN 'TRUE' ELSE 'FALSE' END; +END; +$$; + +SELECT * +-- DELETE +FROM tcg.public.Error ERROR +LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON ERROR.error_type_id = ERROR_TYPE.error_type_id +; +SELECT * +FROM tcg.public.Error_Type ERROR_TYPE +; +SELECT * +FROM tcg.public.TCG_Change_Set CHANGE_SET +ORDER BY CHANGE_SET.change_set_id DESC +; + +SELECT * +-- DELETE +FROM tcg.public.TCG_MTG_Game_Session_Member_Temp +; +SELECT * +-- DELETE +FROM tcg.public.TCG_MTG_Game_Session_Member SESSION_MEMBER +LEFT JOIN tcg.public.TCG_MTG_Game GAME ON SESSION_MEMBER.game_id = GAME.game_id +; + + + diff --git a/static/PostgreSQL/71301_usp_TCG_Statistic_Calc.sql b/static/PostgreSQL/71301_usp_TCG_Statistic_Calc.sql index 5a12031..a13e24d 100644 --- a/static/PostgreSQL/71301_usp_TCG_Statistic_Calc.sql +++ b/static/PostgreSQL/71301_usp_TCG_Statistic_Calc.sql @@ -854,6 +854,7 @@ BEGIN AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order INNER JOIN Temp_Statistic_Calc_Round_Player_Damage T_PLAYER_DAMAGE ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.player_id AND T_PLAYER_DAMAGE.received_from_commander_player_id IS NOT NULL GROUP BY ALL_PLAYER_ROUND.game_id @@ -889,6 +890,7 @@ BEGIN AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order INNER JOIN Temp_Statistic_Calc_Round_Player_Damage T_PLAYER_DAMAGE ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.player_id AND T_PLAYER_DAMAGE.received_from_commander_player_id = ALL_PLAYER_ROUND.player_id GROUP BY ALL_PLAYER_ROUND.game_id @@ -910,6 +912,7 @@ BEGIN AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order INNER JOIN Temp_Statistic_Calc_Round_Player_Damage T_PLAYER_DAMAGE ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.player_id AND T_PLAYER_DAMAGE.life_loss > 0 GROUP BY ALL_PLAYER_ROUND.game_id @@ -931,6 +934,7 @@ BEGIN AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order INNER JOIN Temp_Statistic_Calc_Round_Player_Damage T_PLAYER_DAMAGE ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.player_id GROUP BY ALL_PLAYER_ROUND.game_id , ALL_PLAYER_ROUND.player_id @@ -951,6 +955,7 @@ BEGIN AND T_ROUND_PLAYER.display_order >= T_ROUND_DAMAGE.display_order INNER JOIN Temp_Statistic_Calc_Round_Player_Damage T_PLAYER_DAMAGE ON T_ROUND_DAMAGE.round_id = T_PLAYER_DAMAGE.round_id + AND ALL_PLAYER_ROUND.player_id = T_PLAYER_DAMAGE.player_id AND T_PLAYER_DAMAGE.life_gain > 0 GROUP BY ALL_PLAYER_ROUND.game_id @@ -1010,7 +1015,7 @@ BEGIN INNER JOIN Temp_Statistic_Calc_Game T_GAME ON T_PLAYER_ROUND_LINK.game_id = T_GAME.game_id WHERE T_PLAYER_ROUND_LINK.max_total_commander_damage_received >= v_commander_damage_limit - OR T_PLAYER_ROUND_LINK.total_damage_received >= T_GAME.starting_life + OR T_PLAYER_ROUND_LINK.total_damage_received - T_PLAYER_ROUND_LINK.total_life_gained >= T_GAME.starting_life OR T_PLAYER_ROUND_LINK.is_eliminated GROUP BY T_PLAYER_ROUND_LINK.player_id @@ -9376,6 +9381,8 @@ BEGIN IF NOT EXISTS (SELECT * FROM Temp_Statistic_Calc_Error T_ERROR WHERE T_ERROR.error_type_id <> v_warning_error_type_id LIMIT 1) THEN + DELETE FROM tcg.public.TCG_Statistic; + -- Statistic INSERT INTO tcg.public.TCG_Statistic ( entity_type_code diff --git a/static/css/pages/tcg/decks.css b/static/css/pages/tcg/decks.css index 32355f1..a919a04 100644 --- a/static/css/pages/tcg/decks.css +++ b/static/css/pages/tcg/decks.css @@ -1,8 +1,7 @@ .tcg-card { - margin-top: 1vh; - margin-bottom: 0; + margin: 1vh 0 auto; } diff --git a/static/css/pages/tcg/game.css b/static/css/pages/tcg/game.css index 35ab82c..693e5fc 100644 --- a/static/css/pages/tcg/game.css +++ b/static/css/pages/tcg/game.css @@ -1,5 +1,9 @@ /* MTG Single Game Page Styles */ +.tcg-title.dirty { + background-color: var(--tcg-accent-purple); +} + #buttonHamburger { display: none; } @@ -100,7 +104,7 @@ .control-group { display: flex; align-items: center; - gap: 1rem; + gap: 0.5rem; } .control-group .tcg-input { @@ -113,7 +117,7 @@ .player-names-grid { display: flex; flex-wrap: wrap; - gap: 1rem; + gap: 0.5rem; max-width: 800px; margin: 0 auto 2rem; justify-content: center; @@ -230,7 +234,7 @@ transition: all 0.4s ease; animation: tcg-scaleIn 0.5s ease-out backwards; width: fit-content; - max-width: 38vw; + max-width: 35vw; min-width: 20vw; margin: 0 auto; } @@ -256,7 +260,7 @@ align-items: center; margin-bottom: 1.5rem; flex-wrap: wrap; - gap: 1rem; + gap: 0.5rem; } .player-info { @@ -353,7 +357,7 @@ .life-gain-controls, .life-loss-controls { display: flex; - gap: 1rem; + gap: 0.5rem; justify-content: center; margin-bottom: 1vh; } @@ -364,7 +368,7 @@ border: 2px solid var(--tcg-border-color); color: var(--tcg-text-primary); width: 60px; - height: 60px; + height: 45px; border-radius: 12px; font-family: 'Cinzel', serif; font-size: 1.8rem; diff --git a/static/css/sections/tcg.css b/static/css/sections/tcg.css index cf0015d..5e5d07e 100644 --- a/static/css/sections/tcg.css +++ b/static/css/sections/tcg.css @@ -16,7 +16,7 @@ #pageBody { max-height: 82vh; padding: 0 5vw; - margin: 0; + margin: 0 auto; border: 0; align-content: center; justify-content: flex-start; @@ -25,7 +25,6 @@ align-items: flex-start; overflow-y: auto; overflow-x: hidden; - position: absolute; width: 90vw; color: var(--colour-text); } diff --git a/static/dist/css/tcg_decks.bundle.css b/static/dist/css/tcg_decks.bundle.css index dbee99f..29aa615 100644 --- a/static/dist/css/tcg_decks.bundle.css +++ b/static/dist/css/tcg_decks.bundle.css @@ -16,7 +16,7 @@ #pageBody { max-height: 82vh; padding: 0 5vw; - margin: 0; + margin: 0 auto; border: 0; align-content: center; justify-content: flex-start; @@ -25,7 +25,6 @@ align-items: flex-start; overflow-y: auto; overflow-x: hidden; - position: absolute; width: 90vw; color: var(--colour-text); } @@ -67,8 +66,7 @@ .tcg-card { - margin-top: 1vh; - margin-bottom: 0; + margin: 1vh 0 auto; } diff --git a/static/dist/css/tcg_decks.bundle.css.map b/static/dist/css/tcg_decks.bundle.css.map index 1433190..3cb924d 100644 --- a/static/dist/css/tcg_decks.bundle.css.map +++ b/static/dist/css/tcg_decks.bundle.css.map @@ -1 +1 @@ -{"version":3,"file":"css/tcg_decks.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;;;AC/DA;IACI,eAAe;IACf,gBAAgB;AACpB;;;AAGA;IACI,gBAAgB;IAChB,gBAAgB;AACpB;;AAEA;IACI,aAAa;AACjB;AACA;IACI,yCAAyC;AAC7C;AACA;IACI,gBAAgB;IAChB,gBAAgB;AACpB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/decks.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","\n\n.tcg-card {\n margin-top: 1vh;\n margin-bottom: 0;\n}\n\n\ntable.table-main tbody {\n max-height: 30vh;\n overflow-y: auto;\n}\n\ntable.statistics {\n margin-top: 0;\n}\ntable.statistics thead {\n background-color: var(--background-color);\n}\ntable.statistics tbody {\n max-height: 30vh;\n overflow-y: auto;\n}\ntable.statistics thead tr th.deck,\ntable.statistics tbody tr td.deck_id {\n min-width: 20vh;\n max-width: 20vh;\n}\ntable.statistics thead tr th.name,\ntable.statistics tbody tr td.name {\n min-width: 40vh;\n max-width: 40vh;\n}\ntable.statistics thead tr th.value,\ntable.statistics tbody tr td.value {\n min-width: 10vh;\n max-width: 10vh;\n}"],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"css/tcg_decks.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;;;AC9DA;IACI,kBAAkB;AACtB;;;AAGA;IACI,gBAAgB;IAChB,gBAAgB;AACpB;;AAEA;IACI,aAAa;AACjB;AACA;IACI,yCAAyC;AAC7C;AACA;IACI,gBAAgB;IAChB,gBAAgB;AACpB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/decks.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0 auto;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","\n\n.tcg-card {\n margin: 1vh 0 auto;\n}\n\n\ntable.table-main tbody {\n max-height: 30vh;\n overflow-y: auto;\n}\n\ntable.statistics {\n margin-top: 0;\n}\ntable.statistics thead {\n background-color: var(--background-color);\n}\ntable.statistics tbody {\n max-height: 30vh;\n overflow-y: auto;\n}\ntable.statistics thead tr th.deck,\ntable.statistics tbody tr td.deck_id {\n min-width: 20vh;\n max-width: 20vh;\n}\ntable.statistics thead tr th.name,\ntable.statistics tbody tr td.name {\n min-width: 40vh;\n max-width: 40vh;\n}\ntable.statistics thead tr th.value,\ntable.statistics tbody tr td.value {\n min-width: 10vh;\n max-width: 10vh;\n}"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/static/dist/css/tcg_game.bundle.css b/static/dist/css/tcg_game.bundle.css index 7093907..4400774 100644 --- a/static/dist/css/tcg_game.bundle.css +++ b/static/dist/css/tcg_game.bundle.css @@ -16,7 +16,7 @@ #pageBody { max-height: 82vh; padding: 0 5vw; - margin: 0; + margin: 0 auto; border: 0; align-content: center; justify-content: flex-start; @@ -25,7 +25,6 @@ align-items: flex-start; overflow-y: auto; overflow-x: hidden; - position: absolute; width: 90vw; color: var(--colour-text); } @@ -66,6 +65,10 @@ } /* MTG Single Game Page Styles */ +.tcg-title.dirty { + background-color: var(--tcg-accent-purple); +} + #buttonHamburger { display: none; } @@ -166,7 +169,7 @@ .control-group { display: flex; align-items: center; - gap: 1rem; + gap: 0.5rem; } .control-group .tcg-input { @@ -179,7 +182,7 @@ .player-names-grid { display: flex; flex-wrap: wrap; - gap: 1rem; + gap: 0.5rem; max-width: 800px; margin: 0 auto 2rem; justify-content: center; @@ -296,7 +299,7 @@ transition: all 0.4s ease; animation: tcg-scaleIn 0.5s ease-out backwards; width: fit-content; - max-width: 38vw; + max-width: 35vw; min-width: 20vw; margin: 0 auto; } @@ -322,7 +325,7 @@ align-items: center; margin-bottom: 1.5rem; flex-wrap: wrap; - gap: 1rem; + gap: 0.5rem; } .player-info { @@ -419,7 +422,7 @@ .life-gain-controls, .life-loss-controls { display: flex; - gap: 1rem; + gap: 0.5rem; justify-content: center; margin-bottom: 1vh; } @@ -430,7 +433,7 @@ border: 2px solid var(--tcg-border-color); color: var(--tcg-text-primary); width: 60px; - height: 60px; + height: 45px; border-radius: 12px; font-family: 'Cinzel', serif; font-size: 1.8rem; diff --git a/static/dist/css/tcg_game.bundle.css.map b/static/dist/css/tcg_game.bundle.css.map index a9e50d8..509855d 100644 --- a/static/dist/css/tcg_game.bundle.css.map +++ b/static/dist/css/tcg_game.bundle.css.map @@ -1 +1 @@ -{"version":3,"file":"css/tcg_game.bundle.css","mappings":"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","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/game.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","/* MTG Single Game Page Styles */\n\n#buttonHamburger {\n display: none;\n}\n\n/* Game Header */\n.game-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin: 1vh auto;\n flex-wrap: wrap;\n gap: 0;\n animation: tcg-fadeInDown 0.8s ease-out;\n}\n\n.header-left, .header-right {\n flex: 1;\n color: var(--tcg-text-secondary);\n font-size: 1rem;\n margin: 0 auto;\n}\n\n.header-left {\n padding-left: 15vw;\n width: 30vw;\n}\n\n.header-right {\n text-align: right;\n min-width: 15vw;\n width: 15vw;\n}\n\n.header-center {\n text-align: center;\n flex: 2;\n padding-left: 4vw;\n}\n\n.game-header .container.save.button-cancel {\n width: 15vw;\n max-width: 15vw;\n}\n\n.back-link {\n color: var(--tcg-text-secondary);\n text-decoration: none;\n font-family: 'Cinzel', serif;\n font-size: 1rem;\n transition: color 0.3s ease;\n}\n\n.back-link:hover {\n color: var(--tcg-accent-gold);\n}\n\n.game-title {\n font-family: 'Cinzel', serif;\n font-size: 2.5rem;\n font-weight: 700;\n background: linear-gradient(135deg, var(--tcg-accent-gold), var(--tcg-accent-purple));\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n margin-bottom: 0.5rem;\n letter-spacing: 0.05em;\n}\n\n.game-meta {\n display: flex;\n gap: 0;\n justify-content: center;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.game-meta .location {\n color: var(--tcg-text-secondary);\n font-size: 1rem;\n width: 4vw;\n}\n\n/* Setup Section */\n.setup-section {\n max-width: 800px;\n margin: 0 auto 2rem;\n animation: tcg-fadeIn 0.8s ease-out 0.2s backwards;\n}\n\n.setup-controls {\n display: flex;\n gap: 2rem;\n justify-content: center;\n flex-wrap: wrap;\n margin-bottom: 2rem;\n}\n\n.control-group {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.control-group .tcg-input {\n width: 80px;\n text-align: center;\n font-family: 'Cinzel', serif;\n font-size: 1.2rem;\n}\n\n.player-names-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n max-width: 800px;\n margin: 0 auto 2rem;\n justify-content: center;\n}\n\n.player-name-input-wrapper {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n border: 1px solid gray;\n border-radius: 0.5vh;\n padding: 1vh;\n width: fit-content;\n}\n.player-name-input-wrapper.is_collapsed {\n display: none;\n}\n\n.player-name-heading-label,\n.player-name-label {\n font-size: 0.9rem;\n color: var(--tcg-text-secondary);\n letter-spacing: 0.05em;\n}\n.player-name-label {\n font-size: 0.8rem;\n}\n\n.setup-actions {\n text-align: center;\n}\n\n/* Game Section */\n#gameSection {\n margin: 0 auto;\n}\n#gameSection .row.round {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.9rem;\n color: var(--tcg-text-secondary);\n margin: 0 auto 0.5vh;\n width: fit-content;\n}\n#gameSection .row.round .row.round .round.display_order {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: var(--tcg-bg-card);\n border: 1px solid var(--tcg-border-color);\n border-radius: 6px;\n padding: 0.25rem 0.5rem;\n}\n/*\n#gameSection .row.round label {\n margin-left: 30vw;\n color: var(--tcg-text-secondary);\n font-size: 1rem;\n width: 4vw;\n}\n#gameSection .row.round input {\n width: 10vw;\n margin: 0 3vw 1vh;\n}\n*/\n#gameSection .row.round .row.round span.round.display_order {\n font-family: 'Cinzel', serif;\n font-weight: 600;\n color: var(--tcg-text-primary);\n min-width: 20px;\n justify-content: center;\n}\n#gameSection .row.round .row.round button.btn-round-display-order {\n background: transparent;\n border: none;\n color: var(--tcg-text-secondary);\n cursor: pointer;\n font-size: 1rem;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n}\n#gameSection .row.round .row.round button.btn-round-display-order:hover {\n color: var(--tcg-accent-red);\n transform: scale(1.2);\n}\n\n/* Players Grid */\n.players-grid {\n display: flex; /* grid;\n grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));\n */\n gap: 2rem;\n margin-bottom: 2rem;\n max-width: 90vw;\n flex-wrap: wrap;\n margin: 0 auto;\n width: fit-content;\n\n}\n\n/* Player Card */\n.player-card {\n background: var(--tcg-bg-secondary);\n border: 2px solid var(--tcg-border-color);\n border-radius: 16px;\n padding: 1.5rem;\n position: relative;\n overflow: hidden;\n transition: all 0.4s ease;\n animation: tcg-scaleIn 0.5s ease-out backwards;\n width: fit-content;\n max-width: 38vw;\n min-width: 20vw;\n margin: 0 auto;\n}\n\n.player-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 4px;\n background: linear-gradient(90deg, var(--tcg-accent-purple), var(--tcg-accent-gold));\n}\n\n.player-card.eliminated {\n opacity: 0.5;\n filter: grayscale(0.8);\n}\n\n.player-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1.5rem;\n flex-wrap: wrap;\n gap: 1rem;\n}\n\n.player-info {\n flex: 1;\n min-width: 150px;\n}\n\n.player-name {\n font-family: 'Cinzel', serif;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--tcg-accent-gold);\n letter-spacing: 0.05em;\n margin-bottom: 0.5rem;\n}\n\n.commander-deaths {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.9rem;\n color: var(--tcg-text-secondary);\n}\n\n.death-counter {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: var(--tcg-bg-card);\n border: 1px solid var(--tcg-border-color);\n border-radius: 6px;\n padding: 0.25rem 0.5rem;\n}\n\n.death-display {\n font-family: 'Cinzel', serif;\n font-weight: 600;\n color: var(--tcg-text-primary);\n min-width: 20px;\n text-align: center;\n}\n\n.death-btn {\n background: transparent;\n border: none;\n color: var(--tcg-text-secondary);\n cursor: pointer;\n font-size: 1rem;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n}\n\n.death-btn:hover {\n color: var(--tcg-accent-red);\n transform: scale(1.2);\n}\n\n.eliminate-btn {\n background: var(--tcg-accent-red);\n color: white;\n border: none;\n padding: 0.5rem 1rem;\n border-radius: 6px;\n font-size: 0.9rem;\n cursor: pointer;\n font-family: 'Cinzel', serif;\n transition: all 0.3s ease;\n}\n\n.eliminate-btn:hover {\n background: #b91c1c;\n transform: scale(1.05);\n}\n\n/* Life Total */\n.life-total {\n text-align: center;\n margin-bottom: 2rem;\n}\n\n.life-display {\n font-family: 'Cinzel', serif;\n font-size: 4rem;\n font-weight: 700;\n color: var(--tcg-text-primary);\n margin-bottom: 1rem;\n text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);\n}\n\n.life-gain-controls,\n.life-loss-controls {\n display: flex;\n gap: 1rem;\n justify-content: center;\n margin-bottom: 1vh;\n}\n\n.life-gain-btn,\n.life-loss-btn {\n background: var(--tcg-bg-card);\n border: 2px solid var(--tcg-border-color);\n color: var(--tcg-text-primary);\n width: 60px;\n height: 60px;\n border-radius: 12px;\n font-family: 'Cinzel', serif;\n font-size: 1.8rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.life-gain-btn:hover,\n.life-loss-btn:hover {\n border-color: green; /*var(--tcg-accent-purple);*/\n background: green; /*var(--tcg-accent-purple);*/\n color: var(--tcg-bg-primary);\n transform: scale(1.1);\n}\n\n.life-loss-btn:hover {\n border-color: red;\n background: red;\n}\n\n.life-gain-btn:active,\n.life-loss-btn:active {\n transform: scale(0.95);\n}\n\n.life-total label {\n color: var(--tcg-text-primary);\n width: 100%;\n margin-bottom: 1vh;\n display: inline-block;\n}\n\n/* Commander Damage Section */\n.commander-damage-section {\n border-top: 1px solid var(--tcg-border-color);\n padding-top: 1.5rem;\n}\n\n.section-title {\n font-family: 'Cinzel', serif;\n font-size: 1.1rem;\n color: var(--tcg-accent-purple);\n margin-bottom: 1rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.damage-grid {\n display: grid;\n gap: 0.75rem;\n}\n\n.damage-row {\n background: var(--tcg-bg-card);\n border: 1px solid var(--tcg-border-color);\n border-radius: 8px;\n padding: 0.75rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n transition: all 0.3s ease;\n}\n\n.damage-row:hover {\n border-color: var(--tcg-accent-purple);\n background: rgba(139, 92, 246, 0.1);\n}\n\n.damage-source {\n font-size: 1rem;\n color: var(--tcg-text-secondary);\n padding-right: 1vh;\n}\n\n.damage-controls {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n}\n\n.damage-display {\n font-family: 'Cinzel', serif;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--tcg-text-primary);\n min-width: 40px;\n text-align: center;\n}\n\n.damage-display.lethal {\n color: var(--tcg-accent-red);\n animation: pulse 1s ease-in-out infinite;\n}\n\n.damage-btn {\n background: var(--tcg-bg-primary);\n border: 1px solid var(--tcg-border-color);\n color: var(--tcg-text-primary);\n width: 36px;\n height: 36px;\n border-radius: 6px;\n font-size: 1.2rem;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.damage-btn:hover {\n border-color: var(--tcg-accent-purple);\n background: var(--tcg-accent-purple);\n color: var(--tcg-bg-primary);\n}\n\n.damage-log.container {\n color: white;\n margin: 2vh auto 0;\n text-align: center;\n}\n.damage-log.container table thead tr th.round_id,\n.damage-log.container table tbody tr td.round_id {\n width: 7vw;\n}\n.damage-log.container table thead tr th.player_id,\n.damage-log.container table tbody tr td.player_id,\n.damage-log.container table thead tr th.received_from_commander_player_id,\n.damage-log.container table tbody tr td.received_from_commander_player_id {\n width: 20vw;\n}\n.damage-log.container table thead tr th.life_gain,\n.damage-log.container table tbody tr td.life_gain,\n.damage-log.container table thead tr th.life_loss,\n.damage-log.container table tbody tr td.life_loss {\n width: 7vw;\n}\n.damage-log.container table thead tr th.commander-deaths,\n.damage-log.container table tbody tr td.commander-deaths {\n width: 7vw;\n}\n.damage-log.container table thead tr th.is_eliminated,\n.damage-log.container table tbody tr td.is_eliminated {\n width: 7vw;\n}\n\n/* Save Indicator */\n.save-indicator {\n position: fixed;\n bottom: 2rem;\n right: 2rem;\n background: var(--tcg-bg-secondary);\n border: 2px solid var(--tcg-accent-gold);\n border-radius: 8px;\n padding: 0.75rem 1.5rem;\n font-family: 'Cinzel', serif;\n color: var(--tcg-accent-gold);\n font-size: 0.9rem;\n opacity: 0;\n transform: translateY(20px);\n transition: all 0.3s ease;\n pointer-events: none;\n z-index: 1000;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);\n}\n\n.save-indicator.show {\n opacity: 1;\n transform: translateY(0);\n}\n\n/* Badges (same as games page) */\n.badge {\n display: inline-block;\n padding: 0.35rem 0.75rem;\n border-radius: 20px;\n font-family: 'Cinzel', serif;\n font-size: 0.8rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.badge-commander {\n background: linear-gradient(135deg, var(--tcg-accent-purple), rgba(139, 92, 246, 0.5));\n color: white;\n margin: 0 auto;\n}\n\n.badge-draft {\n background: linear-gradient(135deg, #2563eb, rgba(37, 99, 235, 0.5));\n color: white;\n}\n\n.badge-sealed {\n background: linear-gradient(135deg, #059669, rgba(5, 150, 105, 0.5));\n color: white;\n}\n\n.badge-standard {\n background: linear-gradient(135deg, var(--tcg-accent-gold), rgba(212, 175, 55, 0.5));\n color: var(--tcg-bg-primary);\n}\n\n/* Hidden Class */\n.hidden {\n display: none !important;\n}\n\n/* Animations */\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .game-header {\n flex-direction: column;\n text-align: center;\n }\n\n .header-left, .header-right {\n text-align: center;\n }\n\n .game-title {\n font-size: 1.8rem;\n }\n\n .players-grid {\n grid-template-columns: 1fr;\n }\n\n .life-display {\n font-size: 3rem;\n }\n\n .life-gain-btn,\n .life-loss-btn {\n width: 50px;\n height: 50px;\n font-size: 1.5rem;\n }\n\n .setup-controls {\n flex-direction: column;\n align-items: center;\n }\n}\n@media (max-width: 1260px) {\n #buttonHamburger {\n display: block;\n }\n}"],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"css/tcg_game.bundle.css","mappings":"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","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/game.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0 auto;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","/* MTG Single Game Page Styles */\n\n.tcg-title.dirty {\n background-color: var(--tcg-accent-purple);\n}\n\n#buttonHamburger {\n display: none;\n}\n\n/* Game Header */\n.game-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin: 1vh auto;\n flex-wrap: wrap;\n gap: 0;\n animation: tcg-fadeInDown 0.8s ease-out;\n}\n\n.header-left, .header-right {\n flex: 1;\n color: var(--tcg-text-secondary);\n font-size: 1rem;\n margin: 0 auto;\n}\n\n.header-left {\n padding-left: 15vw;\n width: 30vw;\n}\n\n.header-right {\n text-align: right;\n min-width: 15vw;\n width: 15vw;\n}\n\n.header-center {\n text-align: center;\n flex: 2;\n padding-left: 4vw;\n}\n\n.game-header .container.save.button-cancel {\n width: 15vw;\n max-width: 15vw;\n}\n\n.back-link {\n color: var(--tcg-text-secondary);\n text-decoration: none;\n font-family: 'Cinzel', serif;\n font-size: 1rem;\n transition: color 0.3s ease;\n}\n\n.back-link:hover {\n color: var(--tcg-accent-gold);\n}\n\n.game-title {\n font-family: 'Cinzel', serif;\n font-size: 2.5rem;\n font-weight: 700;\n background: linear-gradient(135deg, var(--tcg-accent-gold), var(--tcg-accent-purple));\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n margin-bottom: 0.5rem;\n letter-spacing: 0.05em;\n}\n\n.game-meta {\n display: flex;\n gap: 0;\n justify-content: center;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.game-meta .location {\n color: var(--tcg-text-secondary);\n font-size: 1rem;\n width: 4vw;\n}\n\n/* Setup Section */\n.setup-section {\n max-width: 800px;\n margin: 0 auto 2rem;\n animation: tcg-fadeIn 0.8s ease-out 0.2s backwards;\n}\n\n.setup-controls {\n display: flex;\n gap: 2rem;\n justify-content: center;\n flex-wrap: wrap;\n margin-bottom: 2rem;\n}\n\n.control-group {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.control-group .tcg-input {\n width: 80px;\n text-align: center;\n font-family: 'Cinzel', serif;\n font-size: 1.2rem;\n}\n\n.player-names-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n max-width: 800px;\n margin: 0 auto 2rem;\n justify-content: center;\n}\n\n.player-name-input-wrapper {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n border: 1px solid gray;\n border-radius: 0.5vh;\n padding: 1vh;\n width: fit-content;\n}\n.player-name-input-wrapper.is_collapsed {\n display: none;\n}\n\n.player-name-heading-label,\n.player-name-label {\n font-size: 0.9rem;\n color: var(--tcg-text-secondary);\n letter-spacing: 0.05em;\n}\n.player-name-label {\n font-size: 0.8rem;\n}\n\n.setup-actions {\n text-align: center;\n}\n\n/* Game Section */\n#gameSection {\n margin: 0 auto;\n}\n#gameSection .row.round {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.9rem;\n color: var(--tcg-text-secondary);\n margin: 0 auto 0.5vh;\n width: fit-content;\n}\n#gameSection .row.round .row.round .round.display_order {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: var(--tcg-bg-card);\n border: 1px solid var(--tcg-border-color);\n border-radius: 6px;\n padding: 0.25rem 0.5rem;\n}\n/*\n#gameSection .row.round label {\n margin-left: 30vw;\n color: var(--tcg-text-secondary);\n font-size: 1rem;\n width: 4vw;\n}\n#gameSection .row.round input {\n width: 10vw;\n margin: 0 3vw 1vh;\n}\n*/\n#gameSection .row.round .row.round span.round.display_order {\n font-family: 'Cinzel', serif;\n font-weight: 600;\n color: var(--tcg-text-primary);\n min-width: 20px;\n justify-content: center;\n}\n#gameSection .row.round .row.round button.btn-round-display-order {\n background: transparent;\n border: none;\n color: var(--tcg-text-secondary);\n cursor: pointer;\n font-size: 1rem;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n}\n#gameSection .row.round .row.round button.btn-round-display-order:hover {\n color: var(--tcg-accent-red);\n transform: scale(1.2);\n}\n\n/* Players Grid */\n.players-grid {\n display: flex; /* grid;\n grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));\n */\n gap: 2rem;\n margin-bottom: 2rem;\n max-width: 90vw;\n flex-wrap: wrap;\n margin: 0 auto;\n width: fit-content;\n\n}\n\n/* Player Card */\n.player-card {\n background: var(--tcg-bg-secondary);\n border: 2px solid var(--tcg-border-color);\n border-radius: 16px;\n padding: 1.5rem;\n position: relative;\n overflow: hidden;\n transition: all 0.4s ease;\n animation: tcg-scaleIn 0.5s ease-out backwards;\n width: fit-content;\n max-width: 35vw;\n min-width: 20vw;\n margin: 0 auto;\n}\n\n.player-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 4px;\n background: linear-gradient(90deg, var(--tcg-accent-purple), var(--tcg-accent-gold));\n}\n\n.player-card.eliminated {\n opacity: 0.5;\n filter: grayscale(0.8);\n}\n\n.player-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1.5rem;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.player-info {\n flex: 1;\n min-width: 150px;\n}\n\n.player-name {\n font-family: 'Cinzel', serif;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--tcg-accent-gold);\n letter-spacing: 0.05em;\n margin-bottom: 0.5rem;\n}\n\n.commander-deaths {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.9rem;\n color: var(--tcg-text-secondary);\n}\n\n.death-counter {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: var(--tcg-bg-card);\n border: 1px solid var(--tcg-border-color);\n border-radius: 6px;\n padding: 0.25rem 0.5rem;\n}\n\n.death-display {\n font-family: 'Cinzel', serif;\n font-weight: 600;\n color: var(--tcg-text-primary);\n min-width: 20px;\n text-align: center;\n}\n\n.death-btn {\n background: transparent;\n border: none;\n color: var(--tcg-text-secondary);\n cursor: pointer;\n font-size: 1rem;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n}\n\n.death-btn:hover {\n color: var(--tcg-accent-red);\n transform: scale(1.2);\n}\n\n.eliminate-btn {\n background: var(--tcg-accent-red);\n color: white;\n border: none;\n padding: 0.5rem 1rem;\n border-radius: 6px;\n font-size: 0.9rem;\n cursor: pointer;\n font-family: 'Cinzel', serif;\n transition: all 0.3s ease;\n}\n\n.eliminate-btn:hover {\n background: #b91c1c;\n transform: scale(1.05);\n}\n\n/* Life Total */\n.life-total {\n text-align: center;\n margin-bottom: 2rem;\n}\n\n.life-display {\n font-family: 'Cinzel', serif;\n font-size: 4rem;\n font-weight: 700;\n color: var(--tcg-text-primary);\n margin-bottom: 1rem;\n text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);\n}\n\n.life-gain-controls,\n.life-loss-controls {\n display: flex;\n gap: 0.5rem;\n justify-content: center;\n margin-bottom: 1vh;\n}\n\n.life-gain-btn,\n.life-loss-btn {\n background: var(--tcg-bg-card);\n border: 2px solid var(--tcg-border-color);\n color: var(--tcg-text-primary);\n width: 60px;\n height: 45px;\n border-radius: 12px;\n font-family: 'Cinzel', serif;\n font-size: 1.8rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.life-gain-btn:hover,\n.life-loss-btn:hover {\n border-color: green; /*var(--tcg-accent-purple);*/\n background: green; /*var(--tcg-accent-purple);*/\n color: var(--tcg-bg-primary);\n transform: scale(1.1);\n}\n\n.life-loss-btn:hover {\n border-color: red;\n background: red;\n}\n\n.life-gain-btn:active,\n.life-loss-btn:active {\n transform: scale(0.95);\n}\n\n.life-total label {\n color: var(--tcg-text-primary);\n width: 100%;\n margin-bottom: 1vh;\n display: inline-block;\n}\n\n/* Commander Damage Section */\n.commander-damage-section {\n border-top: 1px solid var(--tcg-border-color);\n padding-top: 1.5rem;\n}\n\n.section-title {\n font-family: 'Cinzel', serif;\n font-size: 1.1rem;\n color: var(--tcg-accent-purple);\n margin-bottom: 1rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.damage-grid {\n display: grid;\n gap: 0.75rem;\n}\n\n.damage-row {\n background: var(--tcg-bg-card);\n border: 1px solid var(--tcg-border-color);\n border-radius: 8px;\n padding: 0.75rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n transition: all 0.3s ease;\n}\n\n.damage-row:hover {\n border-color: var(--tcg-accent-purple);\n background: rgba(139, 92, 246, 0.1);\n}\n\n.damage-source {\n font-size: 1rem;\n color: var(--tcg-text-secondary);\n padding-right: 1vh;\n}\n\n.damage-controls {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n}\n\n.damage-display {\n font-family: 'Cinzel', serif;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--tcg-text-primary);\n min-width: 40px;\n text-align: center;\n}\n\n.damage-display.lethal {\n color: var(--tcg-accent-red);\n animation: pulse 1s ease-in-out infinite;\n}\n\n.damage-btn {\n background: var(--tcg-bg-primary);\n border: 1px solid var(--tcg-border-color);\n color: var(--tcg-text-primary);\n width: 36px;\n height: 36px;\n border-radius: 6px;\n font-size: 1.2rem;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.damage-btn:hover {\n border-color: var(--tcg-accent-purple);\n background: var(--tcg-accent-purple);\n color: var(--tcg-bg-primary);\n}\n\n.damage-log.container {\n color: white;\n margin: 2vh auto 0;\n text-align: center;\n}\n.damage-log.container table thead tr th.round_id,\n.damage-log.container table tbody tr td.round_id {\n width: 7vw;\n}\n.damage-log.container table thead tr th.player_id,\n.damage-log.container table tbody tr td.player_id,\n.damage-log.container table thead tr th.received_from_commander_player_id,\n.damage-log.container table tbody tr td.received_from_commander_player_id {\n width: 20vw;\n}\n.damage-log.container table thead tr th.life_gain,\n.damage-log.container table tbody tr td.life_gain,\n.damage-log.container table thead tr th.life_loss,\n.damage-log.container table tbody tr td.life_loss {\n width: 7vw;\n}\n.damage-log.container table thead tr th.commander-deaths,\n.damage-log.container table tbody tr td.commander-deaths {\n width: 7vw;\n}\n.damage-log.container table thead tr th.is_eliminated,\n.damage-log.container table tbody tr td.is_eliminated {\n width: 7vw;\n}\n\n/* Save Indicator */\n.save-indicator {\n position: fixed;\n bottom: 2rem;\n right: 2rem;\n background: var(--tcg-bg-secondary);\n border: 2px solid var(--tcg-accent-gold);\n border-radius: 8px;\n padding: 0.75rem 1.5rem;\n font-family: 'Cinzel', serif;\n color: var(--tcg-accent-gold);\n font-size: 0.9rem;\n opacity: 0;\n transform: translateY(20px);\n transition: all 0.3s ease;\n pointer-events: none;\n z-index: 1000;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);\n}\n\n.save-indicator.show {\n opacity: 1;\n transform: translateY(0);\n}\n\n/* Badges (same as games page) */\n.badge {\n display: inline-block;\n padding: 0.35rem 0.75rem;\n border-radius: 20px;\n font-family: 'Cinzel', serif;\n font-size: 0.8rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.badge-commander {\n background: linear-gradient(135deg, var(--tcg-accent-purple), rgba(139, 92, 246, 0.5));\n color: white;\n margin: 0 auto;\n}\n\n.badge-draft {\n background: linear-gradient(135deg, #2563eb, rgba(37, 99, 235, 0.5));\n color: white;\n}\n\n.badge-sealed {\n background: linear-gradient(135deg, #059669, rgba(5, 150, 105, 0.5));\n color: white;\n}\n\n.badge-standard {\n background: linear-gradient(135deg, var(--tcg-accent-gold), rgba(212, 175, 55, 0.5));\n color: var(--tcg-bg-primary);\n}\n\n/* Hidden Class */\n.hidden {\n display: none !important;\n}\n\n/* Animations */\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .game-header {\n flex-direction: column;\n text-align: center;\n }\n\n .header-left, .header-right {\n text-align: center;\n }\n\n .game-title {\n font-size: 1.8rem;\n }\n\n .players-grid {\n grid-template-columns: 1fr;\n }\n\n .life-display {\n font-size: 3rem;\n }\n\n .life-gain-btn,\n .life-loss-btn {\n width: 50px;\n height: 50px;\n font-size: 1.5rem;\n }\n\n .setup-controls {\n flex-direction: column;\n align-items: center;\n }\n}\n@media (max-width: 1260px) {\n #buttonHamburger {\n display: block;\n }\n}"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/static/dist/css/tcg_games.bundle.css b/static/dist/css/tcg_games.bundle.css index 181eec4..debf69e 100644 --- a/static/dist/css/tcg_games.bundle.css +++ b/static/dist/css/tcg_games.bundle.css @@ -16,7 +16,7 @@ #pageBody { max-height: 82vh; padding: 0 5vw; - margin: 0; + margin: 0 auto; border: 0; align-content: center; justify-content: flex-start; @@ -25,7 +25,6 @@ align-items: flex-start; overflow-y: auto; overflow-x: hidden; - position: absolute; width: 90vw; color: var(--colour-text); } diff --git a/static/dist/css/tcg_games.bundle.css.map b/static/dist/css/tcg_games.bundle.css.map index e7773e2..404f69b 100644 --- a/static/dist/css/tcg_games.bundle.css.map +++ b/static/dist/css/tcg_games.bundle.css.map @@ -1 +1 @@ -{"version":3,"file":"css/tcg_games.bundle.css","mappings":"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","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/games.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","/* MTG Games Page Styles */\n\n/* Page Header */\n.page-header {\n text-align: center;\n margin-bottom: 3rem;\n animation: tcg-fadeInDown 0.8s ease-out;\n margin: 0 auto;\n}\n\n.page-title {\n font-family: 'Cinzel', serif;\n font-size: 3rem;\n font-weight: 700;\n background: linear-gradient(135deg, var(--tcg-accent-gold), var(--tcg-accent-purple));\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n margin-bottom: 0.5rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.page-subtitle {\n font-size: 1.2rem;\n color: var(--tcg-text-secondary);\n letter-spacing: 0.15em;\n text-transform: uppercase;\n}\n\n/* Games Section */\n.games-section {\n position: relative;\n animation: tcg-fadeIn 0.8s ease-out 0.2s backwards;\n margin: 2vh auto;\n display: flex;\n flex-wrap: wrap;\n}\n\n.section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1rem;\n flex-wrap: wrap;\n gap: 1rem;\n width: 100%;\n}\n\n/* Filters Form */\n.filters-form {\n margin-bottom: 2rem;\n padding: 1.5rem;\n background: var(--tcg-bg-card);\n border: 1px solid var(--tcg-border-color);\n border-radius: 12px;\n}\n\n.filters-row {\n display: flex;\n gap: 1.5rem;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n min-width: 150px;\n}\n\n.filter-group.checkbox-group {\n flex-direction: row;\n align-items: center;\n gap: 0.75rem;\n}\n\n.filter-group.checkbox-group input[type=\"checkbox\"] {\n width: 20px;\n height: 20px;\n accent-color: var(--tcg-accent-purple);\n}\n\n.filter-group.checkbox-group .tcg-label {\n margin-bottom: 0;\n}\n\n/* Games Table */\n.games-table-container {\n overflow-x: auto;\n}\n\n#tableMain.games-table {\n border-collapse: collapse;\n font-size: 1rem;\n}\n\n.games-table thead {\n background: var(--tcg-bg-card);\n border-bottom: 2px solid var(--tcg-accent-purple);\n}\n.games-table th {\n font-family: 'Cinzel', serif;\n font-size: 0.95rem;\n font-weight: 600;\n color: var(--tcg-accent-gold);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n padding: 1rem;\n}\n.games-table thead tr {\n height: 4vh;\n}\n\n#tableMain.games-table tbody {\n max-height: 59vh;\n}\n.games-table tbody tr {\n border-bottom: 1px solid var(--tcg-border-color);\n transition: all 0.3s ease;\n height: 4vh;\n}\n.games-table tbody tr:hover {\n background: rgba(139, 92, 246, 0.1);\n}\n.games-table tbody tr.inactive {\n opacity: 0.5;\n}\n\n.games-table td {\n padding: 1rem;\n vertical-align: middle;\n}\n.games-table tbody td.game-location,\n.games-table tbody td.game-date {\n color: white;\n}\n\n.games-table thead tr th.game_id,\n.games-table tbody tr td.game_id {\n min-width: 10vh;\n max-width: 10vh;\n}\n.games-table thead tr th.is_commander,\n.games-table tbody tr td.is_commander {\n min-width: 12vh;\n max-width: 12vh;\n}\n.games-table thead tr th.location_name,\n.games-table tbody tr td.location_name {\n min-width: 20vh;\n max-width: 20vh;\n}\n.games-table thead tr th.start_on,\n.games-table tbody tr td.start_on {\n min-width: 14vh;\n max-width: 14vh;\n}\n#tableMain.games-table thead tr th.active,\n#tableMain.games-table tbody tr td.active {\n min-width: 8vh;\n max-width: 8vh;\n}\n.games-table thead tr th.navMtgGame,\n.games-table tbody tr td.navMtgGame {\n min-width: 13vh;\n max-width: 13vh;\n}\n\n.game_id {\n font-family: 'Cinzel', serif;\n font-weight: 600;\n color: var(--tcg-text-secondary);\n}\n\n/* Badges */\n.badge {\n display: inline-block;\n padding: 0.35rem 0.75rem;\n border-radius: 20px;\n font-family: 'Cinzel', serif;\n font-size: 0.8rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.badge-commander {\n background: linear-gradient(135deg, var(--tcg-accent-purple), rgba(139, 92, 246, 0.5));\n color: white;\n}\n\n.badge-draft {\n background: linear-gradient(135deg, #2563eb, rgba(37, 99, 235, 0.5));\n color: white;\n}\n\n.badge-sealed {\n background: linear-gradient(135deg, #059669, rgba(5, 150, 105, 0.5));\n color: white;\n}\n\n.badge-standard {\n background: linear-gradient(135deg, var(--tcg-accent-gold), rgba(212, 175, 55, 0.5));\n color: var(--tcg-bg-primary);\n}\n\n/* Status Indicators */\n.status {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.35rem 0.75rem;\n border-radius: 20px;\n font-size: 0.85rem;\n font-weight: 500;\n}\n\n.status::before {\n content: '';\n width: 8px;\n height: 8px;\n border-radius: 50%;\n}\n\n.status-active {\n background: rgba(34, 197, 94, 0.2);\n color: #22c55e;\n}\n\n.status-active::before {\n background: #22c55e;\n animation: pulse-status 2s ease-in-out infinite;\n}\n\n.status-ended {\n background: rgba(107, 114, 128, 0.2);\n color: #9ca3af;\n}\n\n.status-ended::before {\n background: #9ca3af;\n}\n\n.status-inactive {\n background: rgba(220, 38, 38, 0.2);\n color: #dc2626;\n}\n\n.status-inactive::before {\n background: #dc2626;\n}\n\n@keyframes pulse-status {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n}\n\n/* Join Button */\n.btn-join {\n padding: 0.5vh 1vw;\n font-size: 0.9rem;\n}\n\n/* No Games Message */\n.no-games {\n text-align: center;\n padding: 3rem !important;\n}\n\n.no-games-message {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n}\n\n.no-games-icon {\n font-size: 3rem;\n opacity: 0.5;\n}\n\n.no-games-message p {\n color: var(--tcg-text-secondary);\n font-size: 1.1rem;\n}\n\n/* Modal */\n.modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: tcg-fadeIn 0.3s ease-out;\n}\n\n.modal-overlay.is_collapsed {\n display: none;\n}\n\n.modal-content {\n width: 90%;\n max-width: 500px;\n max-height: 90vh;\n overflow-y: auto;\n animation: tcg-scaleIn 0.3s ease-out;\n}\n\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1.5rem;\n}\n\n.modal-header .tcg-section-title {\n margin-bottom: 0;\n}\n\n.modal-close {\n background: none;\n border: none;\n color: var(--tcg-text-secondary);\n font-size: 2rem;\n cursor: pointer;\n transition: color 0.3s ease;\n line-height: 1;\n}\n\n.modal-close:hover {\n color: var(--tcg-accent-red);\n}\n\n/* New Game Form */\n.new-game-form {\n display: flex;\n flex-direction: column;\n gap: 1.25rem;\n}\n\n.form-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.form-group textarea.tcg-input {\n resize: vertical;\n min-height: 80px;\n}\n\n.form-group select.tcg-input {\n cursor: pointer;\n}\n\n.form-actions {\n display: flex;\n gap: 1rem;\n justify-content: flex-end;\n margin-top: 1rem;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .page-title {\n font-size: 2rem;\n }\n\n .section-header {\n align-items: stretch;\n }\n\n .filters-row {\n flex-direction: column;\n }\n\n .filter-group {\n width: 100%;\n }\n\n .games-table th,\n .games-table td {\n padding: 0.75rem 0.5rem;\n font-size: 0.9rem;\n }\n\n .btn-join {\n padding: 0.4rem 0.75rem;\n font-size: 0.8rem;\n }\n\n .modal-content {\n width: 95%;\n padding: 1.5rem;\n }\n}\n"],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"css/tcg_games.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;AChEA,0BAA0B;;AAE1B,gBAAgB;AAChB;IACI,kBAAkB;IAClB,mBAAmB;IACnB,uCAAuC;IACvC,cAAc;AAClB;;AAEA;IACI,4BAA4B;IAC5B,eAAe;IACf,gBAAgB;IAChB,qFAAqF;IACrF,6BAA6B;IAC7B,oCAAoC;IACpC,qBAAqB;IACrB,qBAAqB;IACrB,sBAAsB;IACtB,yBAAyB;AAC7B;;AAEA;IACI,iBAAiB;IACjB,gCAAgC;IAChC,sBAAsB;IACtB,yBAAyB;AAC7B;;AAEA,kBAAkB;AAClB;IACI,kBAAkB;IAClB,kDAAkD;IAClD,gBAAgB;IAChB,aAAa;IACb,eAAe;AACnB;;AAEA;IACI,aAAa;IACb,8BAA8B;IAC9B,mBAAmB;IACnB,mBAAmB;IACnB,eAAe;IACf,SAAS;IACT,WAAW;AACf;;AAEA,iBAAiB;AACjB;IACI,mBAAmB;IACnB,eAAe;IACf,8BAA8B;IAC9B,yCAAyC;IACzC,mBAAmB;AACvB;;AAEA;IACI,aAAa;IACb,WAAW;IACX,qBAAqB;IACrB,eAAe;AACnB;;AAEA;IACI,aAAa;IACb,sBAAsB;IACtB,WAAW;IACX,gBAAgB;AACpB;;AAEA;IACI,mBAAmB;IACnB,mBAAmB;IACnB,YAAY;AAChB;;AAEA;IACI,WAAW;IACX,YAAY;IACZ,sCAAsC;AAC1C;;AAEA;IACI,gBAAgB;AACpB;;AAEA,gBAAgB;AAChB;IACI,gBAAgB;AACpB;;AAEA;IACI,yBAAyB;IACzB,eAAe;AACnB;;AAEA;IACI,8BAA8B;IAC9B,iDAAiD;AACrD;AACA;IACI,4BAA4B;IAC5B,kBAAkB;IAClB,gBAAgB;IAChB,6BAA6B;IAC7B,yBAAyB;IACzB,sBAAsB;IACtB,aAAa;AACjB;AACA;IACI,WAAW;AACf;;AAEA;IACI,gBAAgB;AACpB;AACA;IACI,gDAAgD;IAChD,yBAAyB;IACzB,WAAW;AACf;AACA;IACI,mCAAmC;AACvC;AACA;IACI,YAAY;AAChB;;AAEA;IACI,aAAa;IACb,sBAAsB;AAC1B;AACA;;IAEI,YAAY;AAChB;;AAEA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,cAAc;IACd,cAAc;AAClB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;;AAEA;IACI,4BAA4B;IAC5B,gBAAgB;IAChB,gCAAgC;AACpC;;AAEA,WAAW;AACX;IACI,qBAAqB;IACrB,wBAAwB;IACxB,mBAAmB;IACnB,4BAA4B;IAC5B,iBAAiB;IACjB,gBAAgB;IAChB,yBAAyB;IACzB,sBAAsB;AAC1B;;AAEA;IACI,sFAAsF;IACtF,YAAY;AAChB;;AAEA;IACI,oEAAoE;IACpE,YAAY;AAChB;;AAEA;IACI,oEAAoE;IACpE,YAAY;AAChB;;AAEA;IACI,oFAAoF;IACpF,4BAA4B;AAChC;;AAEA,sBAAsB;AACtB;IACI,oBAAoB;IACpB,mBAAmB;IACnB,WAAW;IACX,wBAAwB;IACxB,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;AACpB;;AAEA;IACI,WAAW;IACX,UAAU;IACV,WAAW;IACX,kBAAkB;AACtB;;AAEA;IACI,kCAAkC;IAClC,cAAc;AAClB;;AAEA;IACI,mBAAmB;IACnB,+CAA+C;AACnD;;AAEA;IACI,oCAAoC;IACpC,cAAc;AAClB;;AAEA;IACI,mBAAmB;AACvB;;AAEA;IACI,kCAAkC;IAClC,cAAc;AAClB;;AAEA;IACI,mBAAmB;AACvB;;AAEA;IACI,WAAW,UAAU,EAAE;IACvB,MAAM,YAAY,EAAE;AACxB;;AAEA,gBAAgB;AAChB;IACI,kBAAkB;IAClB,iBAAiB;AACrB;;AAEA,qBAAqB;AACrB;IACI,kBAAkB;IAClB,wBAAwB;AAC5B;;AAEA;IACI,aAAa;IACb,sBAAsB;IACtB,mBAAmB;IACnB,SAAS;AACb;;AAEA;IACI,eAAe;IACf,YAAY;AAChB;;AAEA;IACI,gCAAgC;IAChC,iBAAiB;AACrB;;AAEA,UAAU;AACV;IACI,eAAe;IACf,MAAM;IACN,OAAO;IACP,QAAQ;IACR,SAAS;IACT,8BAA8B;IAC9B,aAAa;IACb,mBAAmB;IACnB,uBAAuB;IACvB,aAAa;IACb,mCAAmC;AACvC;;AAEA;IACI,aAAa;AACjB;;AAEA;IACI,UAAU;IACV,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,oCAAoC;AACxC;;AAEA;IACI,aAAa;IACb,8BAA8B;IAC9B,mBAAmB;IACnB,qBAAqB;AACzB;;AAEA;IACI,gBAAgB;AACpB;;AAEA;IACI,gBAAgB;IAChB,YAAY;IACZ,gCAAgC;IAChC,eAAe;IACf,eAAe;IACf,2BAA2B;IAC3B,cAAc;AAClB;;AAEA;IACI,4BAA4B;AAChC;;AAEA,kBAAkB;AAClB;IACI,aAAa;IACb,sBAAsB;IACtB,YAAY;AAChB;;AAEA;IACI,aAAa;IACb,sBAAsB;IACtB,WAAW;AACf;;AAEA;IACI,gBAAgB;IAChB,gBAAgB;AACpB;;AAEA;IACI,eAAe;AACnB;;AAEA;IACI,aAAa;IACb,SAAS;IACT,yBAAyB;IACzB,gBAAgB;AACpB;;AAEA,eAAe;AACf;IACI;QACI,eAAe;IACnB;;IAEA;QACI,oBAAoB;IACxB;;IAEA;QACI,sBAAsB;IAC1B;;IAEA;QACI,WAAW;IACf;;IAEA;;QAEI,uBAAuB;QACvB,iBAAiB;IACrB;;IAEA;QACI,uBAAuB;QACvB,iBAAiB;IACrB;;IAEA;QACI,UAAU;QACV,eAAe;IACnB;AACJ","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/games.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0 auto;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","/* MTG Games Page Styles */\n\n/* Page Header */\n.page-header {\n text-align: center;\n margin-bottom: 3rem;\n animation: tcg-fadeInDown 0.8s ease-out;\n margin: 0 auto;\n}\n\n.page-title {\n font-family: 'Cinzel', serif;\n font-size: 3rem;\n font-weight: 700;\n background: linear-gradient(135deg, var(--tcg-accent-gold), var(--tcg-accent-purple));\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n margin-bottom: 0.5rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.page-subtitle {\n font-size: 1.2rem;\n color: var(--tcg-text-secondary);\n letter-spacing: 0.15em;\n text-transform: uppercase;\n}\n\n/* Games Section */\n.games-section {\n position: relative;\n animation: tcg-fadeIn 0.8s ease-out 0.2s backwards;\n margin: 2vh auto;\n display: flex;\n flex-wrap: wrap;\n}\n\n.section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1rem;\n flex-wrap: wrap;\n gap: 1rem;\n width: 100%;\n}\n\n/* Filters Form */\n.filters-form {\n margin-bottom: 2rem;\n padding: 1.5rem;\n background: var(--tcg-bg-card);\n border: 1px solid var(--tcg-border-color);\n border-radius: 12px;\n}\n\n.filters-row {\n display: flex;\n gap: 1.5rem;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n min-width: 150px;\n}\n\n.filter-group.checkbox-group {\n flex-direction: row;\n align-items: center;\n gap: 0.75rem;\n}\n\n.filter-group.checkbox-group input[type=\"checkbox\"] {\n width: 20px;\n height: 20px;\n accent-color: var(--tcg-accent-purple);\n}\n\n.filter-group.checkbox-group .tcg-label {\n margin-bottom: 0;\n}\n\n/* Games Table */\n.games-table-container {\n overflow-x: auto;\n}\n\n#tableMain.games-table {\n border-collapse: collapse;\n font-size: 1rem;\n}\n\n.games-table thead {\n background: var(--tcg-bg-card);\n border-bottom: 2px solid var(--tcg-accent-purple);\n}\n.games-table th {\n font-family: 'Cinzel', serif;\n font-size: 0.95rem;\n font-weight: 600;\n color: var(--tcg-accent-gold);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n padding: 1rem;\n}\n.games-table thead tr {\n height: 4vh;\n}\n\n#tableMain.games-table tbody {\n max-height: 59vh;\n}\n.games-table tbody tr {\n border-bottom: 1px solid var(--tcg-border-color);\n transition: all 0.3s ease;\n height: 4vh;\n}\n.games-table tbody tr:hover {\n background: rgba(139, 92, 246, 0.1);\n}\n.games-table tbody tr.inactive {\n opacity: 0.5;\n}\n\n.games-table td {\n padding: 1rem;\n vertical-align: middle;\n}\n.games-table tbody td.game-location,\n.games-table tbody td.game-date {\n color: white;\n}\n\n.games-table thead tr th.game_id,\n.games-table tbody tr td.game_id {\n min-width: 10vh;\n max-width: 10vh;\n}\n.games-table thead tr th.is_commander,\n.games-table tbody tr td.is_commander {\n min-width: 12vh;\n max-width: 12vh;\n}\n.games-table thead tr th.location_name,\n.games-table tbody tr td.location_name {\n min-width: 20vh;\n max-width: 20vh;\n}\n.games-table thead tr th.start_on,\n.games-table tbody tr td.start_on {\n min-width: 14vh;\n max-width: 14vh;\n}\n#tableMain.games-table thead tr th.active,\n#tableMain.games-table tbody tr td.active {\n min-width: 8vh;\n max-width: 8vh;\n}\n.games-table thead tr th.navMtgGame,\n.games-table tbody tr td.navMtgGame {\n min-width: 13vh;\n max-width: 13vh;\n}\n\n.game_id {\n font-family: 'Cinzel', serif;\n font-weight: 600;\n color: var(--tcg-text-secondary);\n}\n\n/* Badges */\n.badge {\n display: inline-block;\n padding: 0.35rem 0.75rem;\n border-radius: 20px;\n font-family: 'Cinzel', serif;\n font-size: 0.8rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n}\n\n.badge-commander {\n background: linear-gradient(135deg, var(--tcg-accent-purple), rgba(139, 92, 246, 0.5));\n color: white;\n}\n\n.badge-draft {\n background: linear-gradient(135deg, #2563eb, rgba(37, 99, 235, 0.5));\n color: white;\n}\n\n.badge-sealed {\n background: linear-gradient(135deg, #059669, rgba(5, 150, 105, 0.5));\n color: white;\n}\n\n.badge-standard {\n background: linear-gradient(135deg, var(--tcg-accent-gold), rgba(212, 175, 55, 0.5));\n color: var(--tcg-bg-primary);\n}\n\n/* Status Indicators */\n.status {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.35rem 0.75rem;\n border-radius: 20px;\n font-size: 0.85rem;\n font-weight: 500;\n}\n\n.status::before {\n content: '';\n width: 8px;\n height: 8px;\n border-radius: 50%;\n}\n\n.status-active {\n background: rgba(34, 197, 94, 0.2);\n color: #22c55e;\n}\n\n.status-active::before {\n background: #22c55e;\n animation: pulse-status 2s ease-in-out infinite;\n}\n\n.status-ended {\n background: rgba(107, 114, 128, 0.2);\n color: #9ca3af;\n}\n\n.status-ended::before {\n background: #9ca3af;\n}\n\n.status-inactive {\n background: rgba(220, 38, 38, 0.2);\n color: #dc2626;\n}\n\n.status-inactive::before {\n background: #dc2626;\n}\n\n@keyframes pulse-status {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n}\n\n/* Join Button */\n.btn-join {\n padding: 0.5vh 1vw;\n font-size: 0.9rem;\n}\n\n/* No Games Message */\n.no-games {\n text-align: center;\n padding: 3rem !important;\n}\n\n.no-games-message {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n}\n\n.no-games-icon {\n font-size: 3rem;\n opacity: 0.5;\n}\n\n.no-games-message p {\n color: var(--tcg-text-secondary);\n font-size: 1.1rem;\n}\n\n/* Modal */\n.modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: tcg-fadeIn 0.3s ease-out;\n}\n\n.modal-overlay.is_collapsed {\n display: none;\n}\n\n.modal-content {\n width: 90%;\n max-width: 500px;\n max-height: 90vh;\n overflow-y: auto;\n animation: tcg-scaleIn 0.3s ease-out;\n}\n\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1.5rem;\n}\n\n.modal-header .tcg-section-title {\n margin-bottom: 0;\n}\n\n.modal-close {\n background: none;\n border: none;\n color: var(--tcg-text-secondary);\n font-size: 2rem;\n cursor: pointer;\n transition: color 0.3s ease;\n line-height: 1;\n}\n\n.modal-close:hover {\n color: var(--tcg-accent-red);\n}\n\n/* New Game Form */\n.new-game-form {\n display: flex;\n flex-direction: column;\n gap: 1.25rem;\n}\n\n.form-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.form-group textarea.tcg-input {\n resize: vertical;\n min-height: 80px;\n}\n\n.form-group select.tcg-input {\n cursor: pointer;\n}\n\n.form-actions {\n display: flex;\n gap: 1rem;\n justify-content: flex-end;\n margin-top: 1rem;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .page-title {\n font-size: 2rem;\n }\n\n .section-header {\n align-items: stretch;\n }\n\n .filters-row {\n flex-direction: column;\n }\n\n .filter-group {\n width: 100%;\n }\n\n .games-table th,\n .games-table td {\n padding: 0.75rem 0.5rem;\n font-size: 0.9rem;\n }\n\n .btn-join {\n padding: 0.4rem 0.75rem;\n font-size: 0.8rem;\n }\n\n .modal-content {\n width: 95%;\n padding: 1.5rem;\n }\n}\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/static/dist/css/tcg_home.bundle.css b/static/dist/css/tcg_home.bundle.css index 1885227..a89de90 100644 --- a/static/dist/css/tcg_home.bundle.css +++ b/static/dist/css/tcg_home.bundle.css @@ -16,7 +16,7 @@ #pageBody { max-height: 82vh; padding: 0 5vw; - margin: 0; + margin: 0 auto; border: 0; align-content: center; justify-content: flex-start; @@ -25,7 +25,6 @@ align-items: flex-start; overflow-y: auto; overflow-x: hidden; - position: absolute; width: 90vw; color: var(--colour-text); } diff --git a/static/dist/css/tcg_home.bundle.css.map b/static/dist/css/tcg_home.bundle.css.map index 5fbef78..193a2b7 100644 --- a/static/dist/css/tcg_home.bundle.css.map +++ b/static/dist/css/tcg_home.bundle.css.map @@ -1 +1 @@ -{"version":3,"file":"css/tcg_home.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;ACjEA;IACI,iBAAiB;AACrB;AACA;IACI,iBAAiB;IACjB,kBAAkB;AACtB,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/home.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","#pageBody .column .row {\n margin-top: 0.5vh;\n}\n#pageBody .column .row .button {\n margin-left: auto;\n margin-right: auto;\n}"],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"css/tcg_home.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;AChEA;IACI,iBAAiB;AACrB;AACA;IACI,iBAAiB;IACjB,kBAAkB;AACtB,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/home.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0 auto;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","#pageBody .column .row {\n margin-top: 0.5vh;\n}\n#pageBody .column .row .button {\n margin-left: auto;\n margin-right: auto;\n}"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/static/dist/css/user_account.bundle.css b/static/dist/css/user_account.bundle.css index aaf66f3..c8e99a4 100644 --- a/static/dist/css/user_account.bundle.css +++ b/static/dist/css/user_account.bundle.css @@ -16,7 +16,7 @@ #pageBody { max-height: 82vh; padding: 0 5vw; - margin: 0; + margin: 0 auto; border: 0; align-content: center; justify-content: flex-start; @@ -25,7 +25,6 @@ align-items: flex-start; overflow-y: auto; overflow-x: hidden; - position: absolute; width: 90vw; color: var(--colour-text); } diff --git a/static/dist/css/user_account.bundle.css.map b/static/dist/css/user_account.bundle.css.map index 12c04d7..20251a6 100644 --- a/static/dist/css/user_account.bundle.css.map +++ b/static/dist/css/user_account.bundle.css.map @@ -1 +1 @@ -{"version":3,"file":"css/user_account.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;;;AChEA;IACI,aAAa;AACjB;;AAEA;IACI,eAAe;IACf,SAAS;IACT,WAAW;AACf;;AAEA;IACI,cAAc;AAClB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,gBAAgB;AACpB;;AAEA;;;IAGI,kCAAkC;IAClC,2CAA2C;AAC/C,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/user/user.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","\n#formFilters {\n display: none;\n}\n\n.container.save.button-cancel {\n position: fixed;\n top: 10vh;\n right: 10vh;\n}\n\n.container-input {\n margin: 0 auto;\n}\nlabel {\n font-weight: bold;\n}\n.container-input input {\n max-width: 250px;\n}\n\ninput.dirty, \ntextarea.dirty, \nselect.dirty {\n border-color: var(--primary-color);\n background-color: var(--background-color-2);\n}"],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"css/user_account.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;;;AC/DA;IACI,aAAa;AACjB;;AAEA;IACI,eAAe;IACf,SAAS;IACT,WAAW;AACf;;AAEA;IACI,cAAc;AAClB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,gBAAgB;AACpB;;AAEA;;;IAGI,kCAAkC;IAClC,2CAA2C;AAC/C,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/user/user.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0 auto;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","\n#formFilters {\n display: none;\n}\n\n.container.save.button-cancel {\n position: fixed;\n top: 10vh;\n right: 10vh;\n}\n\n.container-input {\n margin: 0 auto;\n}\nlabel {\n font-weight: bold;\n}\n.container-input input {\n max-width: 250px;\n}\n\ninput.dirty, \ntextarea.dirty, \nselect.dirty {\n border-color: var(--primary-color);\n background-color: var(--background-color-2);\n}"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/static/dist/css/user_accounts.bundle.css b/static/dist/css/user_accounts.bundle.css index bebc749..d160c36 100644 --- a/static/dist/css/user_accounts.bundle.css +++ b/static/dist/css/user_accounts.bundle.css @@ -17,7 +17,7 @@ #pageBody { max-height: 82vh; padding: 0 5vw; - margin: 0; + margin: 0 auto; border: 0; align-content: center; justify-content: flex-start; @@ -26,7 +26,6 @@ align-items: flex-start; overflow-y: auto; overflow-x: hidden; - position: absolute; width: 90vw; color: var(--colour-text); } diff --git a/static/dist/css/user_accounts.bundle.css.map b/static/dist/css/user_accounts.bundle.css.map index 1096ff7..3cf607e 100644 --- a/static/dist/css/user_accounts.bundle.css.map +++ b/static/dist/css/user_accounts.bundle.css.map @@ -1 +1 @@ -{"version":3,"file":"css/user_accounts.bundle.css","mappings":";;;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C","sources":["webpack://app/./static/css/sections/tcg.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}"],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"css/user_accounts.bundle.css","mappings":";;;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C","sources":["webpack://app/./static/css/sections/tcg.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0 auto;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/static/dist/js/main.bundle.js b/static/dist/js/main.bundle.js index cff3a3d..3423b86 100644 --- a/static/dist/js/main.bundle.js +++ b/static/dist/js/main.bundle.js @@ -417,6 +417,12 @@ class API { } // MTG Game API methods + static async getIsGameDataOutdated(game) { + const url = `/mtg/api/game/${game[attrGameId]}/is-outdated`; + let dataRequest = {}; + dataRequest[flagGame] = game; + return await API.request(url, 'POST', dataRequest); + } static async saveGame(game, formFilters, comment) { let dataRequest = {}; dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters); @@ -1616,6 +1622,7 @@ class PageMtgDecks extends TableBasePage { + class PageMtgGame extends TableBasePage { static hash = hashPageMtgGame; static attrIdRowObject = attrGameId; @@ -1630,6 +1637,9 @@ class PageMtgGame extends TableBasePage { hookupFilters() { // this.sharedHookupFilters(); } + callFilterTableContent() { + window.location.reload(); + } loadRowTable(rowJson) { return; } @@ -1667,6 +1677,8 @@ class PageMtgGame extends TableBasePage { this.hookupPlayerLifeIncrementButtons(); this.hookupCommanderDamageIncrementButtons(); */ + PageMtgGame.hookupOverlayGameOutdated(); + PageMtgGame.hookupGameUpdateCheck(); } static hookupResetButton() { const resetGameButton = document.querySelector('header.game-header .header-right .btn-tcg.btn-tcg-secondary'); @@ -1722,7 +1734,55 @@ class PageMtgGame extends TableBasePage { } } */ - + static hookupGameUpdateCheck() { + const intervalId = setInterval(async () => { + const isGameDataOutdated = await PageMtgGame.checkLastGameUpdate(); + if (isGameDataOutdated) { + clearInterval(intervalId); + } + }, 30000); + } + static async checkLastGameUpdate() { + try { + // Fetch players, rounds, and damage records from API + const isGameDataOutdatedResponse = await API.getIsGameDataOutdated(game); + const isGameDataOutdated = isGameDataOutdatedResponse[flagData]; + console.log({ + isGameDataOutdatedResponse, + isGameDataOutdated + }); + if (isGameDataOutdated) { + // const gameDataOutdatedLabel = document.querySelector(gameDataOutdatedLabelId); + // gameDataOutdatedLabel.classList.remove(flagIsCollapsed); + const pageTitleElement = document.querySelector('.topnav .tcg-title'); + pageTitleElement.classList.add(flagDirty); + PageMtgGame.showOverlayGameOutdated(); + } + return isGameDataOutdated; + } catch (error) { + console.error('Error checking for game update from server:', error); + } + } + static hookupOverlayGameOutdated() { + Events.initialiseEventHandler(idOverlayGameOutdated + ' button.' + flagCancel, flagInitialised, buttonCancel => { + buttonCancel.addEventListener('click', () => { + let overlay = document.querySelector(idOverlayGameOutdated); + overlay.style.visibility = 'hidden'; + }); + }); + Events.initialiseEventHandler(idOverlayGameOutdated + ' button.' + flagSubmit, flagInitialised, buttonConfirm => { + buttonConfirm.addEventListener('click', () => { + let overlay = document.querySelector(idOverlayGameOutdated); + overlay.style.visibility = 'hidden'; + window.location.reload(); + }); + }); + } + static showOverlayGameOutdated() { + let overlay = document.querySelector(idOverlayGameOutdated); + overlay.classList.remove(flagIsCollapsed); + overlay.style.visibility = 'visible'; + } async loadGameFromServer() { console.log("loading game from server"); try { @@ -1805,7 +1865,7 @@ class PageMtgGame extends TableBasePage { maxCommanderDamageReceived = Math.max(maxCommanderDamageReceived, damageRecords.filter(damage => damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId && damage[attrReceivedFromCommanderPlayerId] != null && previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagLifeLoss]).reduce((a, b) => a + b, 0)); }); const totalDamage = damageRecords.filter(damage => damage[attrPlayerId] == playerId && previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagLifeLoss] - damage[flagLifeGain]).reduce((a, b) => a + b, 0); - let life = startingLife - totalDamage; + let life = game[flagStartingLife] - totalDamage; let isEliminatedByForce = damageRecords.filter(damage => damage[attrPlayerId] == playerId && previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagIsEliminated]).some(Boolean); console.log("renderPlayers"); console.log({ @@ -1887,7 +1947,6 @@ class PageMtgGame extends TableBasePage { if (damage[flagActive] && (damage[flagCommanderDeaths] > 0 || damage[flagLifeGain] != 0 || damage[flagLifeLoss] != 0 || damage[flagIsEliminated]) // && rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0][flagDisplayOrder] <= currentRoundDisplayOrder && previousRoundIds.includes(damage[attrRoundId])) { - debugger; let round = rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0]; let player = players.filter(p => p[attrPlayerId] == damage[attrPlayerId])[0]; let receivedFromPlayer = damage[attrReceivedFromCommanderPlayerId] == null ? { @@ -2020,7 +2079,6 @@ class PageMtgGame extends TableBasePage { // Life gain buttons let lifeGainButtonSelector = '.life-gain-btn'; Events.hookupEventHandler("click", lifeGainButtonSelector, (event, button) => { - debugger; const playerId = parseInt(button.dataset.playerId); const amount = parseInt(button.dataset.amount); const activeRoundId = PageMtgGame.getActiveRoundId(); @@ -2120,7 +2178,7 @@ class PageMtgGame extends TableBasePage { damageRecords[damageIndex][flagLifeLoss] += amount; let isLifeGainNotLoss = false; this.changeLife(playerId // playerId - , -amount // amount + , amount // amount , isLifeGainNotLoss // isLifeGainNotLoss , false // updateDamage , damageIndex // damageIndex @@ -2228,7 +2286,7 @@ class PageMtgGame extends TableBasePage { maxDamageFromOtherCommander, totalDamageTaken }); - return hasDamageWithIsEliminated || maxDamageFromOtherCommander >= 21 || totalDamageTaken >= startingLife; + return hasDamageWithIsEliminated || maxDamageFromOtherCommander >= 21 || totalDamageTaken >= game[flagStartingLife]; } static updatePlayerSetup() { const playerCountInput = document.getElementById('playerCount'); @@ -2384,6 +2442,19 @@ class PageMtgGame extends TableBasePage { alert(message); } } + updateAndToggleShowButtonsSaveCancel() { + // let pageBody = document.querySelector(idPageBody); + let isDirty = DOM.hasDirtyChildrenContainer(pageBody); + let buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel; + let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave); + let areVisibleSaveCancelButtons = !buttonSave.classList.contains(flagIsCollapsed); + console.log({ + pageBody, + isDirty, + areVisibleSaveCancelButtons + }); + this.toggleShowButtonsSaveCancel(isDirty || areVisibleSaveCancelButtons); + } leave() { super.leave(); } diff --git a/static/dist/js/main.bundle.js.map b/static/dist/js/main.bundle.js.map index de0d4f2..720944b 100644 --- a/static/dist/js/main.bundle.js.map +++ b/static/dist/js/main.bundle.js.map @@ -1 +1 @@ -{"version":3,"file":"js/main.bundle.js","mappings":"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","sources":["webpack://app/./static/js/lib/validation.js","webpack://app/./static/js/dom.js","webpack://app/./static/js/api.js","webpack://app/./static/js/lib/business_objects/business_objects.js","webpack://app/./static/js/lib/events.js","webpack://app/./static/js/lib/local_storage.js","webpack://app/./static/js/lib/utils.js","webpack://app/./static/js/components/common/temporary/overlay_confirm.js","webpack://app/./static/js/pages/base.js","webpack://app/./static/js/components/common/temporary/overlay_error.js","webpack://app/./static/js/pages/base_table.js","webpack://app/./static/js/pages/tcg/mtg_decks.js","webpack://app/./static/js/pages/tcg/mtg_game.js","webpack://app/./static/js/pages/tcg/mtg_games.js","webpack://app/./static/js/pages/tcg/mtg_home.js","webpack://app/./static/js/pages/legal/accessibility_report.js","webpack://app/./static/js/pages/legal/accessibility_statement.js","webpack://app/./static/js/pages/legal/license.js","webpack://app/./static/js/pages/legal/privacy_policy.js","webpack://app/./static/js/pages/legal/retention_schedule.js","webpack://app/./static/js/pages/mixin.js","webpack://app/./static/js/pages/mixin_table.js","webpack://app/./static/js/pages/user/user.js","webpack://app/./static/js/pages/user/users.js","webpack://app/./static/js/router.js","webpack://app/./static/js/app.js","webpack://app/./static/css/main.css?0a91","webpack://app/./static/css/components/button.css?0e0b","webpack://app/./static/css/components/card.css","webpack://app/./static/css/components/dialog.css","webpack://app/./static/css/components/form.css?94e1","webpack://app/./static/css/components/image.css?9f9c","webpack://app/./static/css/components/label.css?b78f","webpack://app/./static/css/components/modal.css","webpack://app/./static/css/components/navigation.css","webpack://app/./static/css/components/overlay.css?6dfd","webpack://app/./static/css/components/table.css?e553","webpack://app/./static/css/layouts/header.css?da75","webpack://app/./static/css/layouts/footer.css?65e3","webpack://app/./static/css/layouts/table-main.css?8c15","webpack://app/./static/css/lib/reset.css","webpack://app/./static/css/lib/typography.css","webpack://app/./static/css/lib/utils.css","webpack://app/./static/css/lib/variables.css","webpack://app/./static/css/themes/dark.css?0cc3"],"sourcesContent":["\nexport default class Validation {\n /*\n isNullOrWhitespace(v) {\n let txt = JSON.stringify(v).replace('/\\s\\g', '');\n return (txt == '' || 'null');\n }\n */\n\n static isEmpty(object) {\n\n let isEmpty = true;\n\n if (object !== null && object !== \"null\" && object !== undefined && object !== \"undefined\") {\n\n if (object.length == undefined) {\n isEmpty = false; // object exists but isn't a collection\n }\n else if (typeof object === \"function\") {\n isEmpty = false; // object is reference\n }\n else { // string or collection\n\n let isString = (typeof object == \"string\");\n\n if (isString) object = object.trim();\n\n if (object.length > 0) {\n\n if (isString) {\n isEmpty = false; // String greater than length 0\n }\n else {\n\n if (typeof object[0] != \"string\") {\n isEmpty = false;\n }\n else {\n for(let i = 0; i < object.length; i++) {\n if (object[i] != \"\") {\n isEmpty = false;\n break\n }\n }\n }\n }\n }\n }\n }\n\n return isEmpty;\n }\n\n static isValidNumber(value, positiveOnly) {\n return !Validation.isEmpty(value) && !isNaN(value) && (!positiveOnly || parseFloat(value) > 0);\n }\n\n static getDataContentType(params) {\n\n var data = null;\n var contentType = '';\n\n if (!Validation.isEmpty(params)) {\n\n if (typeof params === \"string\") {\n data = params;\n contentType = \"application/x-www-form-urlencoded; charset=UTF-8\";\n }\n else {\n data = JSON.stringify(params);\n contentType = \"application/json; charset=UTF-8\";\n }\n }\n\n return { Data: data, ContentType: contentType };\n }\n\n static arrayContainsItem(array, itemValue) {\n\n var hasItem = false;\n\n if (!Validation.isEmpty(array) && !Validation.isEmpty(itemValue)) {\n\n var isJQueryElementArray = array[0] instanceof jQuery;\n\n if (isJQueryElementArray) {\n\n for (let i = 0; i < array.length; i++) {\n\n if (document.querySelectorAll(array[i]).is(itemValue)) {\n hasItem = true;\n break;\n }\n }\n }\n else {\n\n var isDate = array[0] instanceof Date;\n\n if (isDate) {\n \n for (let i = 0; i < array.length; i++) {\n\n if (array[i].getTime() === itemValue.getTime()) {\n hasItem = true;\n break;\n }\n }\n }\n else {\n\n for (let i = 0; i < array.length; i++) {\n\n if (array[i] == itemValue) {\n hasItem = true;\n break;\n }\n }\n }\n }\n }\n\n return hasItem;\n }\n\n static dictHasKey(d, k) {\n return (k in d);\n }\n static areEqualDicts(dict1, dict2) {\n const keys1 = Object.keys(dict1);\n const keys2 = Object.keys(dict2);\n \n if (keys1.length !== keys2.length) {\n return false;\n }\n \n for (let key of keys1) {\n if (dict1[key] !== dict2[key]) {\n return false;\n }\n }\n \n return true;\n }\n\n static imageExists(url, callback) {\n\n var img = new Image();\n\n img.onload = function() { callback(true); };\n img.onerror = function() { callback(false); };\n img.src = url;\n }\n\n static toFixedOrDefault(value, decimalPlaces, defaultValue = null) {\n return Validation.isValidNumber(value) ? parseFloat(value).toFixed(decimalPlaces) : defaultValue;\n }\n}\n","\nimport Utils from \"./lib/utils.js\";\nimport Validation from \"./lib/validation.js\";\n\nexport default class DOM {\n static setElementAttributesValuesCurrentAndPrevious(element, data) {\n DOM.setElementAttributeValueCurrent(element, data);\n DOM.setElementAttributeValuePrevious(element, data);\n }\n static setElementAttributeValueCurrent(element, data) {\n element.setAttribute(attrValueCurrent, data);\n }\n static setElementAttributeValuePrevious(element, data) {\n element.setAttribute(attrValuePrevious, data);\n }\n static setElementValuesCurrentAndPrevious(element, data) {\n DOM.setElementValueCurrent(element, data);\n DOM.setElementAttributeValuePrevious(element, data);\n }\n static setElementValueCurrent(element, data) {\n DOM.setElementAttributeValueCurrent(element, data);\n let tagName = element.tagName.toUpperCase();\n if (element.type === \"checkbox\") {\n element.checked = data;\n }\n else if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') {\n element.value = data;\n }\n else {\n element.textContent = data;\n }\n }\n static setElementValueCurrentIfEmpty(element, data) {\n if (Validation.isEmpty(DOM.getElementValueCurrent(element))) {\n DOM.setElementValueCurrent(element, data);\n }\n }\n static getCellFromElement(element) {\n return element.closest('td');\n }\n static getRowFromElement(element, flagRow) {\n let selector = Validation.isEmpty(flagRow) ? 'tr' : 'tr.' + flagRow;\n return element.closest(selector);\n }\n static getClosestParent(element, parentSelector) {\n let parent = element.parentElement;\n while (parent) {\n if (parent.matches(parentSelector)) {\n return parent;\n }\n parent = parent.parentElement;\n }\n return null;\n }\n static convertForm2JSON(elementForm) {\n let dataForm = {};\n if (Validation.isEmpty(elementForm)) {\n return dataForm;\n }\n let containersFilter = elementForm.querySelectorAll('.' + flagContainerInput + '.' + flagFilter);\n let containerFilter, labelFilter, keyFilter, filter;\n for (let indexFilter = 0; indexFilter < containersFilter.length; indexFilter++) {\n containerFilter = containersFilter[indexFilter];\n labelFilter = containerFilter.querySelector('label');\n keyFilter = labelFilter.getAttribute('for');\n filter = containerFilter.querySelector(`#${keyFilter}`);\n dataForm[keyFilter] = DOM.getElementValueCurrent(filter);\n }\n return dataForm;\n }\n static loadPageBody(contentNew) {\n let pageBody = document.querySelector(idPageBody);\n pageBody.innerHTML = contentNew;\n }\n static getHashPageCurrent() {\n const hashPageCurrent = document.body.dataset.page;\n return hashPageCurrent;\n }\n static updateAndCheckIsElementDirty(element) {\n element.setAttribute(attrValueCurrent, DOM.getElementValueCurrent(element));\n return DOM.isElementDirty(element);\n }\n static isElementDirty(element) {\n let isDirty = element.getAttribute(attrValuePrevious) != element.getAttribute(attrValueCurrent);\n DOM.handleDirtyElement(element, isDirty);\n return isDirty;\n }\n static handleDirtyElement(element, isDirty) {\n DOM.toggleElementHasClassnameFlag(element, isDirty, flagDirty);\n }\n static toggleElementHasClassnameFlag(element, elementHasFlag, flag) {\n let elementAlreadyHasFlag = element.classList.contains(flag);\n if (elementHasFlag == elementAlreadyHasFlag) return;\n if (elementHasFlag) {\n element.classList.add(flag);\n } else {\n element.classList.remove(flag);\n }\n }\n static hasDirtyChildrenContainer(container) {\n if (container == null) return false;\n return container.querySelector('.' + flagDirty) != null;\n }\n static hasDirtyChildrenNotDeletedContainer(container) {\n if (container == null || container.classList.contains(flagDelete)) return false;\n return container.querySelector('.' + flagDirty + ':not(.' + flagDelete + ', .' + flagDelete + ' *)') != null;\n }\n static getElementValueCurrent(element) {\n let returnVal = '';\n \n if (!Validation.isEmpty(element)) {\n \n let tagName = element.tagName.toUpperCase();\n if (element.type === \"checkbox\") {\n returnVal = element.checked;\n }\n /*\n else if (element.classList.contains(flagIsDatePicker)) {\n returnVal = getDatePickerDate(element, adjust4DayLightSavings);\n }\n */\n else if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') {\n returnVal = element.value;\n }\n else if (element.classList.contains(flagButton) && element.classList.contains(flagActive)) { // tagName === 'BUTTON'\n returnVal = element.classList.contains(flagDelete);\n }\n else if (tagName === 'TD') {\n returnVal = DOM.getElementAttributeValueCurrent(element);\n }\n else if (tagName == 'SVG' && element.classList.contains(flagCheckbox)) {\n returnVal = (element.classList.contains(flagIsChecked))\n }\n else {\n returnVal = element.textContent;\n }\n }\n \n if (Validation.isEmpty(returnVal)) returnVal = '';\n \n return returnVal;\n }\n static getElementAttributeValueCurrent(element) {\n if (Validation.isEmpty(element)) return null;\n return element.getAttribute(attrValueCurrent);\n }\n static getElementAttributeValuePrevious(element) {\n if (Validation.isEmpty(element)) return null;\n return element.getAttribute(attrValuePrevious);\n }\n /* base_table.handleChangeElementCellTable\n static updateAndCheckIsTableElementDirty(element) {\n let wasDirty = DOM.isElementDirty(element);\n let row = DOM.getRowFromElement(element);\n let wasDirtyRow = DOM.hasDirtyChildrenNotDeletedContainer(row);\n let isDirty = DOM.updateAndCheckIsElementDirty(element);\n let cell = DOM.getCellFromElement(element);\n Utils.consoleLogIfNotProductionEnvironment({element, row, cell, isDirty, wasDirty});\n if (isDirty != wasDirty) {\n DOM.handleDirtyElement(cell, isDirty);\n let isDirtyRow = DOM.hasDirtyChildrenNotDeletedContainer(row);\n Utils.consoleLogIfNotProductionEnvironment({isDirtyRow, wasDirtyRow});\n if (isDirtyRow != wasDirtyRow) {\n DOM.handleDirtyElement(row, isDirtyRow);\n }\n }\n }\n */\n static scrollToElement(parent, element) {\n // REQUIRED: parent has scroll-bar\n parent.scrollTop(parent.scrollTop() + (element.offset().top - parent.offset().top));\n }\n static isElementInContainer(container, element) {\n\n if (typeof jQuery === 'function') {\n if (container instanceof jQuery) container = container[0];\n if (element instanceof jQuery) element = element[0];\n }\n\n var containerBounds = container.getBoundingClientRect();\n var elementBounds = element.getBoundingClientRect();\n\n return (\n containerBounds.top <= elementBounds.top &&\n containerBounds.left <= elementBounds.left &&\n ((elementBounds.top + elementBounds.height) <= (containerBounds.top + containerBounds.height)) &&\n ((elementBounds.left + elementBounds.width) <= (containerBounds.left + containerBounds.width))\n );\n }\n static alertError(errorType, errorText) {\n alert(errorType + '\\n' + errorText);\n }\n static createOptionUnselectedProductVariation() {\n return {\n [flagProductVariationType]: {\n [flagNameAttrOptionText]: [flagName],\n [flagNameAttrOptionValue]: [attrIdProductVariationType],\n [flagName]: 'Select Variation Type',\n [attrIdProductVariationType]: 0,\n },\n [flagProductVariation]: {\n [flagNameAttrOptionText]: [flagName],\n [flagNameAttrOptionValue]: [attrIdProductVariation],\n [flagName]: 'Select Variation',\n [attrIdProductVariation]: 0,\n },\n };\n }\n static createOption(optionJson) {\n if (Validation.isEmpty(optionJson)) optionJson = {\n text: 'Select',\n value: 0,\n };\n let option = document.createElement('option');\n option.value = optionJson.value;\n option.textContent = optionJson.text;\n option.selected = optionJson.selected;\n return option;\n }\n\n static escapeHtml(text) {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n static unescapeHtml(html) {\n const div = document.createElement('div');\n div.innerHTML = html;\n return div.textContent || div.innerText || '';\n }\n}\n","import DOM from './dom.js';\n\nexport default class API {\n \n static getCsrfToken() {\n return document.querySelector(idCSRFToken).getAttribute('content');\n }\n \n static async request(hashEndpoint, method = 'GET', data = null, params = null) {\n const url = API.getUrlFromHash(hashEndpoint, params);\n const csrfToken = API.getCsrfToken();\n const options = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n [flagCsrfToken]: csrfToken,\n }\n };\n\n if (data && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {\n data = { \n ...data, \n [flagCsrfToken]: csrfToken,\n };\n options.body = JSON.stringify(data);\n }\n\n try {\n const response = await fetch(url, options);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n return await response.json();\n } catch (error) {\n console.error('API request failed:', error);\n throw error;\n }\n }\n \n static getUrlFromHash(hash, params = null) {\n if (hash == null) hash = hashPageHome;\n let url = API.parameteriseUrl(_pathHost + hash, params);\n return url;\n }\n static parameteriseUrl(url, params) {\n if (params) {\n url += '?' + new URLSearchParams(params).toString();\n }\n return url;\n }\n static goToUrl(url) {\n window.location.href = url;\n }\n static goToHash(hash, params = null) {\n const url = API.getUrlFromHash(hash, params);\n API.goToUrl(url);\n }\n\n // specific api calls\n /* Example:\n getUsers: () => request('/users'),\n getUserById: (id) => request(`/users/${id}`),\n createUser: (userData) => request('/users', 'POST', userData),\n updateUser: (id, userData) => request(`/users/${id}`, 'PUT', userData),\n deleteUser: (id) => request(`/users/${id}`, 'DELETE'),\n */\n\n // User\n // user\n static async loginUser() {\n let callback = {};\n callback[flagCallback] = DOM.getHashPageCurrent();\n return await API.request(hashPageUserLogin, 'POST', callback);\n }\n static async saveUsers(users, formFilters, comment) {\n let dataRequest = {};\n dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n dataRequest[flagUser] = users;\n dataRequest[flagComment] = comment;\n return await API.request(hashSaveUserUser, 'POST', dataRequest);\n }\n\n // MTG Game API methods\n static async saveGame(game, formFilters, comment) {\n let dataRequest = {};\n dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n dataRequest[flagGame] = game;\n dataRequest[flagComment] = comment;\n return await API.request(hashSaveGame, 'POST', dataRequest);\n }\n\n static async getGamePlayers(gameId) {\n const url = `/mtg/api/game/${gameId}/players`;\n return await API.request(url, 'GET');\n }\n static async saveGamePlayers(players, formFilters, comment) {\n let dataRequest = {};\n dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n dataRequest[flagPlayer] = players;\n dataRequest[flagComment] = comment;\n return await API.request(hashSaveGamePlayer, 'POST', dataRequest);\n }\n\n static async getGameRounds(gameId) {\n const url = `/mtg/api/game/${gameId}/rounds`;\n return await API.request(url, 'GET');\n }\n\n static async getGameDamageRecords(gameId) {\n const url = `/mtg/api/game/${gameId}/damage-records`;\n return await API.request(url, 'GET');\n }\n static async saveGameRoundPlayerDamages(rounds, damages, formFilters, comment) {\n let dataRequest = {};\n dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n dataRequest[flagDamage] = damages;\n dataRequest[flagRound] = rounds;\n dataRequest[flagComment] = comment;\n return await API.request(hashSaveGameRoundPlayerDamage, 'POST', dataRequest);\n }\n\n\n}\n","\nimport Utils from '../utils.js';\n\nexport default class BusinessObjects {\n static getOptionJsonFromObjectJsonAndKeys(objectJson, keyText, keyValue, valueSelected = null) {\n return {\n text: objectJson[keyText],\n value: objectJson[keyValue],\n selected: (objectJson[keyValue] == valueSelected),\n };\n }\n static getOptionJsonFromObjectJson(objectJson, valueSelected = null) {\n let keyText = objectJson[flagNameAttrOptionText];\n let keyValue = objectJson[flagNameAttrOptionValue];\n // Utils.consoleLogIfNotProductionEnvironment({objectJson, keyText, keyValue});\n return BusinessObjects.getOptionJsonFromObjectJsonAndKeys(objectJson, keyText, keyValue, valueSelected);\n }\n static getObjectText(objectJson) {\n return objectJson == null ? '' : objectJson[objectJson[flagNameAttrOptionText]];\n }\n static getListObjectsFromIdDictAndCsv(idDict, idCsv) {\n let listObjects = [];\n let ids = idCsv.split(',');\n for (let id of ids) {\n listObjects.push(idDict[id]);\n }\n return listObjects;\n }\n}","\nexport default class Events {\n static initialiseEventHandler(selectorElement, classInitialised, eventHandler) {\n document.querySelectorAll(selectorElement).forEach(function(element) {\n if (element.classList.contains(classInitialised)) return;\n eventHandler(element);\n element.classList.add(classInitialised);\n });\n }\n static hookupEventHandler(eventType, selector, callback) {\n Events.initialiseEventHandler(selector, flagInitialised, (element) => {\n element.addEventListener(eventType, (event) => {\n event.stopPropagation();\n callback(event, element);\n });\n });\n }\n}","\nimport Validation from \"./validation.js\";\n\nexport default class LocalStorage {\n/*\nfunction getPageLocalStorage(pageHash) {\n\n let ls;\n try {\n ls = JSON.parse(localStorage.getItem(pageHash));\n } catch {\n\n }\n\n if (Validation.isEmpty(ls)) return {}\n\n return ls;\n}\nfunction getPageLocalStorageCurrent() {\n\n return JSON.parse(localStorage.getItem(hashPageCurrent));\n}\n\nfunction setPageLocalStorage(pageHash, newLS) {\n\n localStorage.setItem(pageHash, JSON.stringify(newLS));\n}\n\nfunction clearPageLocalStorage(pageHash) {\n localStorage.removeItem(pageHash);\n}\n\nfunction setupPageLocalStorage(pageHash) {\n\n let ls = getPageLocalStorage(pageHash);\n\n if (Validation.isEmpty(ls)) ls = {};\n\n setPageLocalStorage(pageHash, ls);\n}\n*/\n\n static getLocalStorage(key) {\n return JSON.parse(localStorage.getItem(key));\n }\n\n static setLocalStorage(key, newLS) {\n localStorage.setItem(key, JSON.stringify(newLS));\n }\n\n/*\nfunction setupPageLocalStorageNext(pageHashNext) {\n let lsOld = getPageLocalStorage(hashPageCurrent);\n hashPageCurrent = pageHashNext;\n clearPageLocalStorage(hashPageCurrent);\n setupPageLocalStorage(hashPageCurrent);\n let lsNew = getPageLocalStorage(hashPageCurrent);\n lsNew[keyBasket] = (keyBasket in lsOld) ? lsOld[keyBasket] : {'items': []};\n setPageLocalStorage(hashPageCurrent, lsNew);\n}\n*/\n}","// Utility functions\n/*\nfunction $(selector) {\n return document.querySelector(selector);\n}\n\nfunction $$(selector) {\n return document.querySelectorAll(selector);\n}\n*/\nexport default class Utils {\n static getListFromDict(dict) {\n let list = [];\n for (let key in dict) {\n list.push(dict[key]);\n }\n return list;\n }\n static consoleLogIfNotProductionEnvironment(message) {\n if (environment.is_production != \"true\") {\n console.log(message);\n }\n }\n}","\nimport Events from \"../../../lib/events.js\";\n\nexport default class OverlayConfirm {\n static hookup(callbackSuccess) {\n Events.initialiseEventHandler(idOverlayConfirm + ' button.' + flagCancel, flagInitialised, (buttonCancel) => {\n buttonCancel.addEventListener('click', () => {\n let overlay = document.querySelector(idOverlayConfirm);\n overlay.style.visibility = 'hidden';\n });\n });\n Events.initialiseEventHandler(idOverlayConfirm + ' button.' + flagSubmit, flagInitialised, (buttonConfirm) => {\n buttonConfirm.addEventListener('click', () => {\n let overlay = document.querySelector(idOverlayConfirm);\n let textarea = overlay.querySelector('textarea');\n overlay.style.visibility = 'hidden';\n callbackSuccess(textarea.value);\n });\n });\n }\n static show() {\n let overlay = document.querySelector(idOverlayConfirm);\n overlay.classList.remove(flagIsCollapsed);\n overlay.style.visibility = 'visible';\n }\n}","\nimport BusinessObjects from \"../lib/business_objects/business_objects.js\";\nimport Events from \"../lib/events.js\";\nimport LocalStorage from \"../lib/local_storage.js\";\nimport API from \"../api.js\";\nimport DOM from \"../dom.js\";\nimport Utils from \"../lib/utils.js\";\n\nimport OverlayConfirm from \"../components/common/temporary/overlay_confirm.js\";\nimport OverlayError from \"../components/common/temporary/overlay_error.js\";\nimport Validation from \"../lib/validation.js\";\n\nexport default class BasePage {\n constructor(router) {\n if (!router) {\n throw new Error(\"Router is required\");\n }\n else {\n Utils.consoleLogIfNotProductionEnvironment(\"initialising with router: \", router);\n }\n this.router = router;\n this.title = titlePageCurrent;\n if (this.constructor === BasePage) {\n throw new Error(\"Cannot instantiate abstract class\");\n }\n \n if (!this.constructor.hash) {\n throw new Error(`Class ${this.constructor.name} must have a static hash attribute.`);\n }\n }\n\n initialize() {\n throw new Error(\"Method 'initialize()' must be implemented.\");\n }\n\n sharedInitialize() {\n this.logInitialisation();\n this.hookupCommonElements();\n }\n\n logInitialisation() {\n Utils.consoleLogIfNotProductionEnvironment('Initialising ' + this.title + ' page');\n }\n \n hookupCommonElements() {\n // hookupVideos();\n this.hookupLogos();\n this.hookupNavigation();\n this.hookupOverlays();\n }\n hookupLogos() {\n Events.hookupEventHandler(\"click\", \".\" + flagImageLogo + \",\" + \".\" + flagLogo, (event, element) => {\n Utils.consoleLogIfNotProductionEnvironment('clicking logo');\n this.router.navigateToHash(hashPageHome);\n });\n }\n /*\n hookupEventHandler(eventType, selector, callback) {\n Events.initialiseEventHandler(selector, flagInitialised, (element) => {\n element.addEventListener(eventType, (event) => {\n event.stopPropagation();\n callback(event, element);\n });\n });\n }\n */\n hookupNavigation() {\n Events.hookupEventHandler(\"click\", idButtonHamburger, (event, element) => {\n let overlayHamburger = document.querySelector(idOverlayHamburger);\n if (overlayHamburger.classList.contains(flagIsCollapsed)) {\n overlayHamburger.classList.remove(flagIsCollapsed);\n overlayHamburger.classList.add(flagExpanded);\n } else {\n overlayHamburger.classList.remove(flagExpanded);\n overlayHamburger.classList.add(flagIsCollapsed);\n }\n });\n\n this.hookupButtonsNavUserAccount();\n this.hookupButtonsNavUserLogout();\n this.hookupButtonsNavUserLogin();\n }\n hookupButtonsNav(buttonSelector) {\n Events.hookupEventHandler(\"click\", buttonSelector, (event, button) => {\n let pageHash = buttonSelector.getAttribute('href');\n this.router.navigateToHash(pageHash); \n });\n }\n hookupButtonsNavUserAccount() {\n // this.hookupButtonsNav('.' + flagNavUserAccount);\n }\n hookupButtonsNavUserLogout() {\n // this.hookupButtonsNav('.' + flagNavUserLogout);\n }\n hookupButtonsNavUserLogin() {\n Events.hookupEventHandler(\"click\", '.' + flagNavUserLogin, (event, navigator) => {\n event.preventDefault();\n event.stopPropagation();\n this.leave();\n API.loginUser()\n .then((response) => {\n if (response.Success) {\n window.location.href = response[flagCallback];\n } else {\n DOM.alertError(\"Error\", response.Message);\n }\n });\n });\n }\n\n hookupOverlays() {\n this.hookupOverlayFromId(idOverlayConfirm);\n this.hookupOverlayFromId(idOverlayError);\n }\n\n hookupOverlayFromId(idOverlay) {\n Events.initialiseEventHandler(idOverlay, flagInitialised, (overlay) => {\n overlay.querySelector('button.' + flagCancel).addEventListener(\"click\", (event) => {\n event.stopPropagation();\n overlay.style.display = 'none';\n });\n });\n }\n\n hookupButtonSave() {\n Events.initialiseEventHandler('.' + flagContainer + '.' + flagSave + '.' + flagCancel + ' button.' + flagSave, flagInitialised, (button) => {\n button.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n button = event.target;\n if (button.classList.contains(flagIsCollapsed)) return;\n Utils.consoleLogIfNotProductionEnvironment('saving page: ', this.title);\n OverlayConfirm.show();\n });\n });\n }\n\n leave() {\n Utils.consoleLogIfNotProductionEnvironment('Leaving ' + this.title + ' page');\n if (this.constructor === BasePage) {\n throw new Error(\"Must implement leave() method.\");\n }\n }\n setLocalStoragePage(dataPage) {\n LocalStorage.setLocalStorage(this.hash, dataPage);\n }\n getLocalStoragePage() {\n return LocalStorage.getLocalStorage(this.hash);\n }\n\n toggleShowButtonsSaveCancel(show, buttonContainerSelector = null) { // , buttonSave = null, buttonCancel = null\n if (Validation.isEmpty(buttonContainerSelector)) buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;\n let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);\n if (buttonSave == null) return;\n let buttonCancel = document.querySelector(buttonContainerSelector + ' ' + idButtonCancel);\n Utils.consoleLogIfNotProductionEnvironment({ show, buttonContainerSelector, buttonCancel, buttonSave });\n if (show) {\n buttonCancel.classList.remove(flagIsCollapsed);\n buttonSave.classList.remove(flagIsCollapsed);\n Utils.consoleLogIfNotProductionEnvironment('showing buttons');\n } else {\n buttonCancel.classList.add(flagIsCollapsed);\n buttonSave.classList.add(flagIsCollapsed);\n Utils.consoleLogIfNotProductionEnvironment('hiding buttons');\n }\n }\n\n static isDirtyFilter(filter) {\n let isDirty = DOM.updateAndCheckIsElementDirty(filter);\n if (isDirty) document.querySelectorAll(idTableMain + ' tbody tr').remove();\n return isDirty;\n }\n\n}","\nimport Events from \"../../../lib/events.js\";\n\nexport default class OverlayError {\n static hookup() {\n Events.initialiseEventHandler(idOverlayError + ' button.' + flagCancel, flagInitialised, (buttonCancel) => {\n buttonCancel.addEventListener('click', () => {\n let overlay = document.querySelector(idOverlayError);\n overlay.style.visibility = 'hidden';\n });\n });\n }\n static show(msgError) {\n let overlay = document.querySelector(idOverlayError);\n let labelError = overlay.querySelector(idLabelError);\n labelError.innerText = msgError;\n overlay.style.visibility = 'visible';\n }\n}","\nimport BusinessObjects from \"../lib/business_objects/business_objects.js\";\nimport Events from \"../lib/events.js\";\nimport LocalStorage from \"../lib/local_storage.js\";\nimport Validation from \"../lib/validation.js\";\nimport BasePage from \"./base.js\";\nimport API from \"../api.js\";\nimport DOM from \"../dom.js\";\nimport Utils from \"../lib/utils.js\";\n\nimport OverlayConfirm from \"../components/common/temporary/overlay_confirm.js\";\nimport OverlayError from \"../components/common/temporary/overlay_error.js\";\n\nexport default class TableBasePage extends BasePage {\n // static hash\n // static attrIdRowObject\n // callSaveTableContent\n\n constructor(router) {\n super(router);\n this.cursorYInitial = null;\n this.rowInitial = null;\n this.placeholder = null;\n this.dragSrcEl = null;\n this.dragSrcRow = null;\n\n this.hookupTableCellDdls = this.hookupTableCellDdls.bind(this);\n }\n \n initialize(isPopState = false) {\n throw new Error(\"Must implement initialize() method.\");\n }\n sharedInitialize(isPopState = false, isSinglePageApp = false) {\n if (!isPopState) {\n super.sharedInitialize();\n this.hookupFilters();\n this.hookupButtonsSaveCancel();\n this.hookupTableMain();\n OverlayConfirm.hookup(() => {\n if (isSinglePageApp) {\n this.saveRecordsTableDirtySinglePageApp();\n }\n else {\n this.saveRecordsTableDirty();\n }\n });\n } else {\n let dataPage = this.getLocalStoragePage();\n let filters = dataPage[flagFormFilters];\n let formFilters = TableBasePage.getFormFilters();\n let filtersDefault = DOM.convertForm2JSON(formFilters);\n if (!Validation.areEqualDicts(filters, filtersDefault)) {\n this.callFilterTableContent();\n }\n }\n }\n hookupFilters() {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Subclass of TableBasePage must implement method hookupFilters().\");\n }\n }\n sharedHookupFilters() {\n this.hookupButtonApplyFilters();\n this.hookupSearchTextFilter();\n }\n hookupFilterActive() {\n let filterSelector = idFormFilters + ' #' + flagActiveOnly;\n let filterActiveOld = document.querySelector(filterSelector);\n filterActiveOld.removeAttribute('id');\n let parentDiv = filterActiveOld.parentElement;\n let isChecked = (DOM.getElementAttributeValuePrevious(parentDiv) == \"True\");\n let filterActiveNew = document.querySelector(idFormFilters + ' div.' + flagActiveOnly + '.' + flagContainerInput + ' svg.' + flagActiveOnly);\n filterActiveNew.setAttribute('id', flagActiveOnly);\n if (isChecked) filterActiveNew.classList.add(flagIsChecked);\n\n Events.hookupEventHandler(\"click\", filterSelector, (event, filterActive) => {\n Utils.consoleLogIfNotProductionEnvironment({ filterActive });\n Utils.consoleLogIfNotProductionEnvironment({ [filterActive.tagName]: filterActive.tagName });\n let svgElement = (filterActive.tagName.toUpperCase() == 'SVG') ? filterActive : filterActive.parentElement;\n let wasChecked = svgElement.classList.contains(flagIsChecked);\n if (wasChecked) {\n svgElement.classList.remove(flagIsChecked);\n }\n else {\n svgElement.classList.add(flagIsChecked);\n }\n return this.handleChangeFilter(event, filterActive);\n });\n let filter = document.querySelector(filterSelector);\n let filterValuePrevious = DOM.getElementValueCurrent(filter);\n filter.setAttribute(attrValueCurrent, filterValuePrevious);\n filter.setAttribute(attrValuePrevious, filterValuePrevious);\n }\n hookupFilter(filterFlag, handler = (event, filter) => { return this.handleChangeFilter(event, filter); }) {\n let filterSelector = idFormFilters + ' #' + filterFlag;\n Events.hookupEventHandler(\"change\", filterSelector, handler);\n let filter = document.querySelector(filterSelector);\n let filterValuePrevious = DOM.getElementValueCurrent(filter);\n filter.setAttribute(attrValueCurrent, filterValuePrevious);\n filter.setAttribute(attrValuePrevious, filterValuePrevious);\n }\n handleChangeFilter(event, filter) {\n let isDirtyFilter = DOM.updateAndCheckIsElementDirty(filter);\n let formFilters = TableBasePage.getFormFilters();\n let areDirtyFilters = isDirtyFilter || DOM.hasDirtyChildrenContainer(formFilters);\n let tbody = document.querySelector(idTableMain + ' tbody');\n let rows = tbody.querySelectorAll(':scope > tr');\n rows.forEach((row) => {\n if (areDirtyFilters && !row.classList.contains(flagIsCollapsed)) row.classList.add(flagIsCollapsed);\n if (!areDirtyFilters && row.classList.contains(flagIsCollapsed)) {\n row.classList.remove(flagIsCollapsed);\n let dirtyInputs = row.querySelectorAll('input.' + flagDirty);\n dirtyInputs.forEach((dirtyInput) => {\n dirtyInput.value = DOM.getElementAttributeValueCurrent(dirtyInput);\n });\n }\n });\n if (areDirtyFilters) {\n /*\n tbody.querySelectorAll('tr').forEach((tr) => { \n if (!DOM.hasDirtyChildrenContainer(tr)) tr.remove(); \n });\n */\n tbody.innerHTML = '
Press \"Apply Filters\" to refresh the table.
' + tbody.innerHTML;\n if (!tbody.classList.contains(flagIsCollapsed)) tbody.classList.add(flagIsCollapsed);\n }\n else {\n let isDirtyLabel = tbody.querySelector(\":scope > div\");\n if (isDirtyLabel != null) isDirtyLabel.remove();\n if (tbody.classList.contains(flagIsCollapsed)) tbody.classList.remove(flagIsCollapsed);\n let initialisedElements = tbody.querySelectorAll('.' + flagInitialised);\n initialisedElements.forEach((initialisedElement) => {\n initialisedElement.classList.remove(flagInitialised);\n });\n this.hookupTableMain();\n }\n this.updateAndToggleShowButtonsSaveCancel();\n }\n hookupFilterIsNotEmpty() {\n this.hookupFilter(flagIsNotEmpty);\n }\n hookupButtonApplyFilters() {\n Events.hookupEventHandler(\"click\", idButtonApplyFilters, (event, button) => {\n event.stopPropagation();\n this.callFilterTableContent();\n });\n }\n hookupSearchTextFilter() {\n this.hookupFilter(flagSearch);\n }\n hookupFilterCommandCategory() {\n this.hookupFilter(attrIdCommandCategory, (event, filterCommandCategory) => {\n this.handleChangeFilter();\n let isDirtyFilter = filterCommandCategory.classList.contains(flagDirty);\n let idCommandCategory = DOM.getElementValueCurrent(filterCommandCategory);\n console.log(\"filter commands unsorted\");\n console.log(Utils.getListFromDict(filterCommands));\n let commandsInCategory = Utils.getListFromDict(filterCommands).filter(command => command[attrIdCommandCategory] == idCommandCategory);\n let sortedCommands = commandsInCategory.sort((a, b) => a[flagName].localeCompare(b[flagName]));\n let filterCommand = document.querySelector(idFormFilters + ' .' + flagCommand);\n let idCommandPrevious = DOM.getElementAttributeValuePrevious(filterCommand);\n filterCommand.innerHTML = '';\n let optionJson, option;\n option = DOM.createOption(null);\n filterCommand.appendChild(option);\n sortedCommands.forEach((command) => {\n optionJson = BusinessObjects.getOptionJsonFromObjectJson(command, idCommandPrevious);\n option = DOM.createOption(optionJson);\n filterCommand.appendChild(option);\n });\n filterCommand.dispatchEvent(new Event('change'));\n return isDirtyFilter;\n });\n }\n hookupFilterCommand() {\n this.hookupFilter(attrIdCommand);\n }\n hookupFilterLocation() {\n this.hookupFilter(attrIdLocation);\n }\n /*\n getAndLoadFilteredTableContent = () => {\n this.callFilterTableContent()\n .catch(error => console.error('Error:', error));\n }\n */\n static getFormFilters() {\n return document.querySelector(idFormFilters);\n }\n callFilterTableContent() {\n let formFilters = TableBasePage.getFormFilters();\n let filtersJson = DOM.convertForm2JSON(formFilters);\n Utils.consoleLogIfNotProductionEnvironment(\"callFilterTableContent\");\n Utils.consoleLogIfNotProductionEnvironment(\"formFilters\");\n Utils.consoleLogIfNotProductionEnvironment(formFilters);\n Utils.consoleLogIfNotProductionEnvironment(\"filtersJson\");\n Utils.consoleLogIfNotProductionEnvironment(filtersJson);\n this.leave();\n API.goToHash(this.constructor.hash, filtersJson);\n }\n callbackLoadTableContent(response) {\n let table = TableBasePage.getTableMain();\n let bodyTable = table.querySelector('tbody');\n bodyTable.querySelectorAll('tr').forEach(function(row) { row.remove(); });\n let rowsJson = response.data[flagRows];\n if (!Validation.isEmpty(rowsJson) && rowsJson.every(row => row.hasOwnProperty('display_order'))) {\n rowsJson = rowsJson.sort((a, b) => a.display_order - b.display_order);\n }\n rowsJson.forEach(this.loadRowTable.bind(this));\n this.hookupTableMain();\n }\n static getTableMain() {\n return document.querySelector(idTableMain);\n }\n loadRowTable(rowJson) {\n throw new Error(\"Subclass of TableBasePage must implement method loadRowTable().\");\n }\n getAndLoadFilteredTableContentSinglePageApp() {\n this.callFilterTableContent()\n .then(data => {\n Utils.consoleLogIfNotProductionEnvironment('Table data received:', data);\n this.callbackLoadTableContent(data);\n })\n .catch(error => console.error('Error:', error));\n }\n hookupButtonsSaveCancel() {\n this.hookupButtonSave();\n this.hookupButtonCancel();\n this.toggleShowButtonsSaveCancel(false);\n }\n saveRecordsTableDirty() {\n let records = this.getTableRecords(true);\n if (records.length == 0) {\n OverlayError.show('No records to save');\n return;\n }\n let formElement = TableBasePage.getFormFilters();\n let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));\n this.callSaveTableContent(records, formElement, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n if (_verbose) { \n Utils.consoleLogIfNotProductionEnvironment('Records saved!');\n Utils.consoleLogIfNotProductionEnvironment('Data received:', data);\n }\n this.callFilterTableContent();\n }\n else {\n Utils.consoleLogIfNotProductionEnvironment(\"error: \", data[flagMessage]);\n OverlayError.show(data[flagMessage]);\n }\n })\n .catch(error => console.error('Error:', error));\n }\n getTableRecords(dirtyOnly = false) {\n let records = [];\n let record;\n document.querySelectorAll(idTableMain + ' > tbody > tr').forEach((row) => {\n if (dirtyOnly && !DOM.hasDirtyChildrenContainer(row)) return;\n record = this.getJsonRow(row);\n records.push(record);\n });\n return records;\n }\n getJsonRow(row) {\n throw new Error(\"Subclass of TableBasePage must implement method getJsonRow().\");\n }\n saveRecordsTableDirtySinglePageApp() {\n let records = this.getTableRecords(true);\n if (records.length == 0) {\n OverlayError.show('No records to save');\n return;\n }\n let formElement = TableBasePage.getFormFilters();\n let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));\n this.callSaveTableContent(records, formElement, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n if (_verbose) { \n Utils.consoleLogIfNotProductionEnvironment('Records saved!');\n Utils.consoleLogIfNotProductionEnvironment('Data received:', data);\n }\n this.callbackLoadTableContent(data);\n }\n else {\n Utils.consoleLogIfNotProductionEnvironment(\"error: \", data[flagMessage]);\n OverlayError.show(data[flagMessage]);\n }\n })\n .catch(error => console.error('Error:', error));\n }\n hookupButtonCancel() {\n Events.initialiseEventHandler('.' + flagContainer + '.' + flagSave + '.' + flagCancel + ' button.' + flagCancel, flagInitialised, (button) => {\n button.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n button = event.target;\n if (button.classList.contains(flagIsCollapsed)) return;\n this.callFilterTableContent();\n });\n button.classList.add(flagIsCollapsed);\n });\n }\n handleClickAddRowTable(event, button) {\n event.stopPropagation();\n _rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - _rowBlank.getAttribute(this.constructor.attrIdRowObject));\n let tbody = document.querySelector(idTableMain + ' tbody');\n if (tbody.classList.contains(flagIsCollapsed)) return;\n let row = _rowBlank.cloneNode(true);\n row.classList.remove(flagInitialised);\n row.querySelectorAll('.' + flagInitialised).forEach(function(element) {\n element.classList.remove(flagInitialised);\n });\n let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;\n row.setAttribute(this.constructor.attrIdRowObject, -1 - countRows);\n this.initialiseRowNew(tbody, row);\n tbody.prepend(row);\n tbody.scrollTop = 0;\n this.hookupTableMain();\n this.postInitialiseRowNewCallback(tbody);\n }\n initialiseRowNew(tbody, row) {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Subclass of TableBasePage must implement method initialiseRowNew().\");\n }\n // row.classList.remove(flagRowNew);\n }\n hookupTableMain() {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Must implement hookupTableMain() method.\");\n }\n Events.initialiseEventHandler(idTableMain, flagInitialised, (table) => {\n this.cacheRowBlank();\n });\n }\n cacheRowBlank() {\n let selectorRowNew = idTableMain + ' tbody tr.' + flagRowNew;\n let rowBlankTemp = document.querySelector(selectorRowNew);\n if (rowBlankTemp == null) return;\n Utils.consoleLogIfNotProductionEnvironment(\"row blank temp: \", rowBlankTemp);\n let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;\n _rowBlank = rowBlankTemp.cloneNode(true);\n document.querySelectorAll(selectorRowNew).forEach(function(row) {\n row.remove();\n });\n _rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - countRows);\n }\n postInitialiseRowNewCallback(tbody) {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Subclass of TableBasePage must implement method postInitialiseRowNewCallback(tbody).\");\n }\n }\n initialiseSliderDisplayOrderRowNew(tbody, row) {\n // let tdSelector = ':scope > tr > td.' + flagDisplayOrder;\n // let tbody = document.querySelector('table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody');\n let slidersDisplayOrder = tbody.querySelectorAll(':scope > tr > td.' + flagDisplayOrder + ' input.' + flagSlider);\n let maxDisplayOrder = 0;\n slidersDisplayOrder.forEach((slider) => {\n maxDisplayOrder = Math.max(maxDisplayOrder, parseFloat(DOM.getElementValueCurrent(slider)));\n });\n let sliderDisplayOrder = row.querySelector('td.' + flagDisplayOrder + ' .' + flagSlider);\n DOM.setElementValuesCurrentAndPrevious(sliderDisplayOrder, maxDisplayOrder + 1);\n }\n hookupSlidersDisplayOrderTable() {\n let selectorDisplayOrder = idTableMain + ' tbody tr td.' + flagDisplayOrder + ' input.' + flagSlider + '.' + flagDisplayOrder;\n this.hookupChangeHandlerTableCells(selectorDisplayOrder);\n }\n hookupChangeHandlerTableCells(inputSelector, handler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n Events.initialiseEventHandler(inputSelector, flagInitialised, (input) => {\n input.addEventListener(\"change\", (event) => {\n handler(event, input);\n });\n handler(null, input);\n });\n }\n handleChangeNestedElementCellTable(event, element) {\n let wasDirtyParentRows = this.getAllIsDirtyRowsInParentTree(element);\n let wasDirtyElement = element.classList.contains(flagDirty);\n let isDirtyElement = DOM.updateAndCheckIsElementDirty(element);\n // Utils.consoleLogIfNotProductionEnvironment({isDirtyElement, wasDirtyElement, wasDirtyParentRows});\n // let td = DOM.getCellFromElement(element);\n // DOM.setElementAttributeValueCurrent(td, DOM.getElementAttributeValueCurrent(element));\n if (isDirtyElement != wasDirtyElement) {\n // DOM.handleDirtyElement(td, isDirtyElement);\n this.updateAndToggleShowButtonsSaveCancel();\n this.cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows);\n }\n }\n getAllIsDirtyRowsInParentTree(element) {\n let rows = [];\n let parent = element;\n let isDirty;\n while (parent) {\n if (parent.tagName.toUpperCase() == 'TR') {\n isDirty = parent.classList.contains(flagDirty)\n rows.push(isDirty);\n }\n parent = parent.parentElement;\n }\n return rows;\n }\n cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows) {\n if (Validation.isEmpty(wasDirtyParentRows)) return;\n let tr = DOM.getRowFromElement(element);\n let isDirtyRow = isDirtyElement || DOM.hasDirtyChildrenContainer(tr);\n let wasDirtyRow = wasDirtyParentRows.shift();\n Utils.consoleLogIfNotProductionEnvironment({isDirtyRow, wasDirtyRow});\n if (isDirtyRow != wasDirtyRow) {\n DOM.handleDirtyElement(tr, isDirtyRow);\n this.updateAndToggleShowButtonsSaveCancel();\n this.cascadeChangedIsDirtyNestedElementCellTable(tr.parentElement, isDirtyRow, wasDirtyParentRows);\n }\n }\n hookupChangeHandlerTableCellsWhenNotCollapsed(inputSelector, handler = (event, element) => {\n if (!element.classList.contains(flagIsCollapsed)) this.handleChangeNestedElementCellTable(event, element);\n }) {\n Events.hookupEventHandler(\"change\", inputSelector, handler);\n }\n hookupFieldsCodeTable() {\n this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagCode + ' > .' + flagCode);\n }\n hookupFieldsNameTable() {\n this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagName + ' > .' + flagName);\n }\n hookupFieldsDescriptionTable() {\n this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagDescription + ' > .' + flagDescription);\n }\n hookupFieldsNotesTable() {\n this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagNotes + ' > .' + flagNotes);\n }\n hookupFieldsActive(flagTable = '', handleClickRowNew = (event, element) => { this.handleClickAddRowTable(event, element); }) {\n let selectorButton = 'table.table-main' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody > tr > td.' + flagActive + ' .' + flagButton + '.' + flagActive;\n let selectorButtonDelete = selectorButton + '.' + flagDelete;\n let selectorButtonUndelete = selectorButton + ':not(.' + flagDelete + ')';\n Utils.consoleLogIfNotProductionEnvironment(\"hookupFieldsActive: \", selectorButtonDelete, selectorButtonUndelete);\n this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete);\n this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete);\n Events.hookupEventHandler(\n \"click\"\n , 'table.table-main' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > thead > tr > th.' + flagActive + ' .' + flagButton + '.' + flagActive\n , (event, button) => { handleClickRowNew(event, button); }\n );\n }\n hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n Events.hookupEventHandler(\"click\", selectorButtonDelete, (event, element) => {\n this.handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });\n });\n }\n handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n if (element.tagName.toUpperCase() != 'SVG') element = element.parentElement;\n let valuePrevious = DOM.getElementAttributeValuePrevious(element);\n let wasDirty = element.classList.contains(flagDirty);\n let row = DOM.getRowFromElement(element);\n if (row.classList.contains(flagRowNew) && !DOM.hasDirtyChildrenContainer(row)) {\n row.parentNode.removeChild(row);\n }\n else {\n let buttonAddTemplate = document.querySelector(idContainerTemplateElements + ' .' + flagButton + '.' + flagActive + '.' + flagAdd);\n let buttonAdd = buttonAddTemplate.cloneNode(true);\n DOM.setElementAttributeValuePrevious(buttonAdd, valuePrevious);\n DOM.setElementAttributeValueCurrent(buttonAdd, false);\n if (wasDirty) buttonAdd.classList.add(flagDirty);\n element.replaceWith(buttonAdd);\n changeHandler(null, buttonAdd);\n this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });\n }\n this.updateAndToggleShowButtonsSaveCancel();\n }\n hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n Events.hookupEventHandler(\"click\", selectorButtonUndelete, (event, element) => {\n this.handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });\n });\n }\n handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n if (element.tagName.toUpperCase() != 'SVG') element = element.parentElement;\n let valuePrevious = DOM.getElementAttributeValuePrevious(element);\n let wasDirty = DOM.isElementDirty(element);\n let buttonDeleteTemplate = document.querySelector(idContainerTemplateElements + ' .' + flagButton + '.' + flagActive + '.' + flagDelete);\n let buttonDelete = buttonDeleteTemplate.cloneNode(true);\n DOM.setElementAttributeValuePrevious(buttonDelete, valuePrevious);\n DOM.setElementAttributeValueCurrent(buttonDelete, true);\n if (wasDirty) buttonDelete.classList.add(flagDirty);\n element.replaceWith(buttonDelete);\n changeHandler(null, buttonDelete);\n this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });\n this.updateAndToggleShowButtonsSaveCancel();\n }\n hookupTdsAccessLevel() {\n this.hookupTableCellDdlPreviews(flagAccessLevel, Utils.getListFromDict(accessLevels));\n }\n hookupTableCellDdlPreviews(\n fieldFlag\n , optionList\n , cellSelector = null\n , ddlHookup = (ddlSelector) => { this.hookupTableCellDdls(ddlSelector); }\n , changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }\n ) {\n if (cellSelector == null) cellSelector = idTableMain + ' > tbody > tr > td.' + fieldFlag;\n Events.hookupEventHandler(\"click\", cellSelector + ' div.' + fieldFlag, (event, div) => {\n this.handleClickTableCellDdlPreview(\n event\n , div\n , fieldFlag\n , optionList\n , cellSelector\n , (ddlSelector) => { ddlHookup(\n ddlSelector\n , (event, element) => { changeHandler(event, element); }\n ); }\n );\n });\n ddlHookup(cellSelector + ' select.' + fieldFlag);\n }\n hookupTableCellDdls(ddlSelector, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n this.hookupChangeHandlerTableCells(ddlSelector, (event, element) => { changeHandler(event, element); });\n }\n handleClickTableCellDdlPreview(event, div, fieldFlag, optionObjectList, cellSelector = null, ddlHookup = (cellSelector) => { this.hookupTableCellDdls(cellSelector); }) {\n if (Validation.isEmpty(cellSelector)) cellSelector = idTableMain + ' > tbody > tr > td.' + fieldFlag;\n let idSelected = DOM.getElementAttributeValueCurrent(div);\n let td = DOM.getCellFromElement(div);\n td.innerHTML = '';\n let ddl = document.createElement('select');\n ddl.classList.add(fieldFlag);\n DOM.setElementValuesCurrentAndPrevious(ddl, idSelected);\n let optionJson, option;\n if (_verbose) { \n Utils.consoleLogIfNotProductionEnvironment(\"click table cell ddl preview\");\n Utils.consoleLogIfNotProductionEnvironment({optionObjectList, cellSelector});\n }\n option = DOM.createOption(null);\n ddl.appendChild(option);\n optionObjectList.forEach((optionObjectJson) => {\n optionJson = BusinessObjects.getOptionJsonFromObjectJson(optionObjectJson, idSelected);\n option = DOM.createOption(optionJson);\n ddl.appendChild(option);\n });\n td.appendChild(ddl);\n let ddlSelector = cellSelector + ' select.' + fieldFlag;\n ddlHookup(ddlSelector);\n }\n /*\n hookupTableCellDDlPreviewsWhenNotCollapsed(cellSelector, optionList, ddlHookup = (event, element) => { this.hookupTableCellDdls(event, element); }) {\n Events.hookupEventHandler(\"click\", cellSelector + ' div', (event, div) => {\n this.handleClickTableCellDdlPreview(event, div, optionList, cellSelector, (event, element) => { ddlHookup(event, element); });\n });\n }\n */\n toggleColumnCollapsed(flagColumn, isCollapsed) {\n this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagIsCollapsed);\n }\n toggleColumnHeaderCollapsed(flagColumn, isCollapsed) {\n this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagIsCollapsed);\n }\n\n hookupFieldsCommandCategory(idTable = null) {\n if (idTable == null) idTable = idTableMain;\n this.hookupTableCellDdlPreviews(\n flagCommandCategory\n , Utils.getListFromDict(filterCommandCategories).sort((a, b) => a[flagName].localeCompare(b[flagName]))\n , idTable + ' > tbody > tr > td.' + flagCommandCategory // + ' .' + flagCommandCategory\n , (cellSelector) => { this.hookupCommandCategoryDdls(cellSelector); }\n );\n }\n hookupCommandCategoryDdls(ddlSelector) {\n this.hookupChangeHandlerTableCells(ddlSelector, (event, element) => { this.handleChangeCommandCategoryDdl(event, element); });\n }\n handleChangeCommandCategoryDdl(event, ddlCategory) {\n let row = DOM.getRowFromElement(ddlCategory);\n let idCommandCategoryRowOld = this.getIdCommandCategoryRow(row); // DOM.getElementAttributeValueCurrent(ddlCategory);\n this.handleChangeNestedElementCellTable(event, ddlCategory);\n let idCommandCategoryRowNew = this.getIdCommandCategoryRow(row); // DOM.getElementAttributeValueCurrent(ddlCategory);\n if (\n idCommandCategoryRowOld == idCommandCategoryRowNew\n || idCommandCategoryRowNew == 0\n ) return;\n console.log({ idCommandCategoryRowNew, idCommandCategoryRowOld });\n let idCommandCategoryFilter = this.getIdCommandCategoryFilter();\n let tdCommand = row.querySelector('td.' + flagCommand);\n tdCommand.dispatchEvent(new Event('click'));\n let ddlCommand = row.querySelector('td.' + flagCommand + ' select.' + flagCommand);\n ddlCommand.innerHTML = '';\n ddlCommand.appendChild(DOM.createOption(null));\n let optionJson, option;\n let commandsInCategory = Utils.getListFromDict(filterCommands).filter(command => \n (\n command[attrIdCommandCategory] == idCommandCategoryRowNew\n || idCommandCategoryRowNew == 0\n )\n && (\n command[attrIdCommandCategory] == idCommandCategoryFilter\n || idCommandCategoryFilter == 0\n )\n );\n let sortedCommands = commandsInCategory.sort((a, b) => a[flagName].localeCompare(b[flagName]));\n sortedCommands.forEach((command) => {\n optionJson = BusinessObjects.getOptionJsonFromObjectJson(command);\n option = DOM.createOption(optionJson);\n ddlCommand.appendChild(option);\n });\n this.handleChangeNestedElementCellTable(event, ddlCommand);\n }\n hookupFieldsCommand(idTable = null) {\n if (idTable == null) idTable = idTableMain;\n Events.hookupEventHandler(\"click\", idTable + ' > tbody > tr > td.' + flagCommand + ' div.' + flagCommand, (event, div) => {\n Utils.consoleLogIfNotProductionEnvironment(div);\n let parentTr = DOM.getRowFromElement(div);\n Utils.consoleLogIfNotProductionEnvironment({ div, parentTr });\n let tdCommandCategory = parentTr.querySelector('td.' + flagCommandCategory);\n let idCommandCategoryRow = this.getIdCommandCategoryRow(parentTr); // DOM.getElementAttributeValueCurrent(tdCommandCategory);\n let idCommandCategoryFilter = this.getIdCommandCategoryFilter();\n let filterCommandList = Utils.getListFromDict(filterCommands);\n let commandsInCategory = filterCommandList.filter(command => \n (\n command[attrIdCommandCategory] == idCommandCategoryRow\n || idCommandCategoryRow == 0\n )\n && (\n command[attrIdCommandCategory] == idCommandCategoryFilter\n || idCommandCategoryFilter == 0\n )\n );\n let sortedCommands = commandsInCategory.sort((a, b) => a[flagName].localeCompare(b[flagName]));\n Utils.consoleLogIfNotProductionEnvironment({ tdCommandCategory, idCommandCategoryRow, idCommandCategoryFilter, filterCommandList, commandsInCategory });\n Utils.consoleLogIfNotProductionEnvironment(filterCommandList);\n this.handleClickTableCellDdlPreview(\n event\n , div\n , flagCommand // fieldFlag\n , sortedCommands // optionList\n , idTable + ' > tbody > tr > td.' + flagCommand // cellSelector\n , (cellSelector) => { this.hookupTableCellDdls(\n cellSelector\n , (event, element) => { this.handleChangeCommandDdl(event, element); }\n ); }\n );\n });\n this.hookupTableCellDdls(\n idTable + ' > tbody > tr > td.' + flagCommand + ' select.' + flagCommand\n , (event, element) => { this.handleChangeCommandDdl(event, element); }\n );\n }\n handleChangeCommandDdl(event, ddlCommand) {\n // console.log(\"handle change command ddl\");\n let row = DOM.getRowFromElement(ddlCommand);\n this.handleChangeNestedElementCellTable(event, ddlCommand);\n let idCommandCategoryRowOld = this.getIdCommandCategoryRow(row);\n let idCommandNew = this.getIdCommandRow(row);\n let commandNew = filterCommands[idCommandNew];\n // console.log({ idCommandCategoryRowOld, commandNew });\n if (commandNew == null || idCommandCategoryRowOld == commandNew[attrIdCommandCategory]) return;\n let divCommandCategory = row.querySelector('td.' + flagCommandCategory + ' div');\n if (divCommandCategory) divCommandCategory.dispatchEvent(new Event('click'));\n let ddlCommandCategory = row.querySelector('td.' + flagCommandCategory + ' select.' + flagCommandCategory);\n DOM.setElementValueCurrent(ddlCommandCategory, commandNew[attrIdCommandCategory]);\n // console.log({ ddlCommandCategory, commandNew });\n this.handleChangeNestedElementCellTable(event, ddlCommandCategory);\n }\n getIdCommandCategoryRow(tr) {\n let elementCommandCategory = tr.querySelector('td.' + flagCommandCategory + ' .' + flagCommandCategory);\n return DOM.getElementAttributeValueCurrent(elementCommandCategory);\n }\n getIdCommandCategoryFilter() {\n let formFilters = TableBasePage.getFormFilters();\n let idCommandCategory = 0;\n if (formFilters == null) return idCommandCategory;\n let commandCategoryFilter = formFilters.querySelector('#' + attrIdCommandCategory);\n let commandFilter = formFilters.querySelector('#' + attrIdCommand);\n let valueCurrentCommandCategoryFilter = DOM.getElementAttributeValueCurrent(commandCategoryFilter);\n Utils.consoleLogIfNotProductionEnvironment({ valueCurrentCommandCategoryFilter });\n if (valueCurrentCommandCategoryFilter == \"\") {\n let valueCurrentCommandFilter = DOM.getElementAttributeValueCurrent(commandFilter);\n Utils.consoleLogIfNotProductionEnvironment({ valueCurrentCommandFilter });\n if (valueCurrentCommandFilter != \"\") {\n let command = filterCommands[valueCurrentCommandFilter];\n idCommandCategory = command[attrIdCommandCategory];\n }\n } else {\n idCommandCategory = parseInt(valueCurrentCommandCategoryFilter);\n }\n return idCommandCategory;\n }\n getHasCommandCategoryFilter() {\n let idCommandCategoryFilter = this.getIdCommandCategoryFilter();\n return !(Validation.isEmpty(idCommandCategoryFilter) || idCommandCategoryFilter == 0);\n }\n getIdCommandRow(tr) {\n let elementCommand = tr.querySelector('td.' + flagCommand + ' .' + flagCommand);\n return DOM.getElementAttributeValueCurrent(elementCommand);\n }\n getIdCommandFilter() {\n let formFilters = TableBasePage.getFormFilters();\n let commandFilter = formFilters.querySelector('#' + attrIdCommand);\n let valueCurrentCommandFilter = DOM.getElementAttributeValueCurrent(commandFilter);\n let idCommand = parseInt(valueCurrentCommandFilter);\n return idCommand;\n }\n getHasCommandFilter() {\n let idCommandFilter = this.getIdCommandFilter();\n return !(Validation.isEmpty(idCommandFilter) || idCommandFilter == 0);\n }\n /*\n createTdActive(isActive) {\n let tdActive = document.createElement(\"td\");\n tdActive.classList.add(flagActive);\n let buttonActive = document.createElement(\"button\");\n buttonActive.classList.add(flagActive);\n buttonActive.classList.add(isActive ? flagDelete : flagAdd);\n buttonActive.textContent = isActive ? 'x' : '+';\n DOM.setElementAttributesValuesCurrentAndPrevious(buttonActive, isActive);\n tdActive.appendChild(buttonActive);\n return tdActive;\n }\n */\n leave() {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Must implement leave() method.\");\n }\n super.leave();\n let formFilters = TableBasePage.getFormFilters();\n let dataPage = {};\n dataPage[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n this.setLocalStoragePage(dataPage);\n }\n\n toggleColumnHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) {\n let table = TableBasePage.getTableMain();\n let columnTh = table.querySelector('th.' + columnFlag);\n let columnThHasFlag = columnTh.classList.contains(classnameFlag);\n if (isRequiredFlag == columnThHasFlag) return;\n DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag);\n }\n toggleColumnHeaderHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) {\n let table = TableBasePage.getTableMain();\n let columnTh = table.querySelector('th.' + columnFlag);\n DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag);\n }\n\n updateAndToggleShowButtonsSaveCancel() {\n // let pageBody = document.querySelector(idPageBody);\n let isDirty = DOM.hasDirtyChildrenContainer(pageBody);\n\n let buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;\n let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);\n let areVisibleSaveCancelButtons = !buttonSave.classList.contains(flagIsCollapsed);\n \n console.log({ pageBody, isDirty, areVisibleSaveCancelButtons });\n\n this.toggleShowButtonsSaveCancel(isDirty || areVisibleSaveCancelButtons);\n }\n}\n","\nimport API from \"../../api.js\";\nimport Events from \"../../lib/events.js\";\nimport TableBasePage from \"../base_table.js\";\nimport Utils from \"../../lib/utils.js\";\n\nexport default class PageMtgDecks extends TableBasePage {\n static hash = hashPageMtgDecks;\n static attrIdRowObject = attrDeckId;\n callSaveTableContent = API.saveDeck;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n hookupFilters() {\n /*\n this.sharedHookupFilters();\n this.hookupFilterActive();\n */\n }\n\n loadRowTable(rowJson) {\n if (rowJson == null) return;\n if (_verbose) { Utils.consoleLogIfNotProductionEnvironment(\"applying data row: \", rowJson); }\n }\n getJsonRow(row) {\n return;\n }\n initialiseRowNew(tbody, row) {\n }\n postInitialiseRowNewCallback(tbody) {\n let newRows = tbody.querySelectorAll('tr.' + flagRowNew);\n let newestRow = newRows[0];\n let clickableElementsSelector = [\n 'td.' + attrCommanderBracketId + ' div.' + attrCommanderBracketId\n ].join('');\n newestRow.querySelectorAll(clickableElementsSelector).forEach((clickableElement) => {\n clickableElement.click();\n });\n }\n\n hookupTableMain() {\n super.hookupTableMain();\n this.hookupTableMainRows();\n this.hookupFieldsNameTable();\n this.hookupTableMainIsCommanderCheckboxes();\n this.hookupTableMainCommanderBracketPreviews();\n this.hookupFieldsActive();\n }\n hookupTableMainRows() {\n return;\n let rowSelector = 'table.' + flagTableMain + ' tbody tr';\n Events.hookupEventHandler(\"click\", rowSelector, (event, row) => {\n let isRowExpanded = row.classList.contains(flagActive);\n let showSection;\n if (isRowExpanded) {\n showSection = false;\n PageMtgDecks.toggleShowDeckStatisticsSection(showSection);\n }\n else {\n showSection = true;\n let deckId = row.getAttribute(attrDeckId);\n let statisticsSectionTableBody = document.querySelector('table.' + flagStatistics + ' tbody');\n statisticsSectionTableBody.innerHTML = '';\n let deck = decks.filter(d => d[attrDeckId] == deckId)[0];\n if (deck[flagStatistics].length > 0) {\n let newStatisticRowsHtml = '';\n deck[flagStatistics]\n .sort((a, b) => a[flagDisplayOrder] - b[flagDisplayOrder])\n .forEach((statistic) => {\n newStatisticRowsHtml += `\n \n ${statistic[flagName]}\n ${statistic[flagValue]}\n \n `;\n });\n statisticsSectionTableBody.innerHTML = newStatisticRowsHtml;\n }\n PageMtgDecks.toggleShowDeckStatisticsSection(showSection);\n }\n });\n }\n static toggleShowDeckStatisticsSection(showSection) {\n let statisticsSectionTableBody = document.querySelector('table.' + flagStatistics + ' tbody');\n if (showSection) {\n statisticsSectionTableBody.classList.remove(flagIsCollapsed);\n }\n else {\n statisticsSectionTableBody.classList.add(flagIsCollapsed);\n }\n }\n hookupTableMainIsCommanderCheckboxes() {\n this.hookupChangeHandlerTableCells(idTableMain + ' td.' + flagIsCommander + ' .' + flagIsCommander);\n }\n hookupTableMainCommanderBracketPreviews() {\n this.hookupTableCellDdlPreviews(\n attrCommanderBracketId\n , Utils.getListFromDict(commanderBrackets)\n );\n }\n \n leave() {\n super.leave();\n }\n}\n","\n\nimport API from \"../../api.js\";\nimport TableBasePage from \"../base_table.js\";\nimport DOM from \"../../dom.js\";\nimport Events from \"../../lib/events.js\";\n\nexport default class PageMtgGame extends TableBasePage {\n static hash = hashPageMtgGame;\n static attrIdRowObject = attrGameId;\n callSaveTableContent = API.saveGame;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n this.hookupTcgGame();\n }\n hookupFilters() {\n // this.sharedHookupFilters();\n }\n loadRowTable(rowJson) {\n return;\n }\n getJsonRow(row) {\n return;\n }\n initialiseRowNew(tbody, row) {\n \n }\n postInitialiseRowNewCallback(tbody) {\n \n }\n\n hookupTableMain() {\n super.hookupTableMain();\n }\n hookupTcgGame() {\n this.initGamePage();\n let pageHeading = document.querySelector('.container.company-name .tcg-title.company-name');\n pageHeading.innerText = `MTG Game #${gameId}`;\n }\n\n initGamePage() {\n // Load existing game state from API or show setup\n PageMtgGame.updatePlayerSetup();\n if (typeof gameId !== 'undefined' && gameId) {\n this.loadGameFromServer();\n }\n /*\n else {\n PageMtgGame.updatePlayerSetup();\n }\n */\n \n PageMtgGame.hookupResetButton();\n PageMtgGame.hookupPlayerCountInput();\n this.hookupStartGameButton();\n /*\n this.hookupCommanderDeathIncrementButtons();\n this.hookupEliminateCommanderButtons();\n this.hookupPlayerLifeIncrementButtons();\n this.hookupCommanderDamageIncrementButtons();\n */\n }\n static hookupResetButton() {\n const resetGameButton = document.querySelector('header.game-header .header-right .btn-tcg.btn-tcg-secondary');\n if (resetGameButton) {\n resetGameButton.addEventListener('click', PageMtgGame.resetGame);\n }\n }\n static hookupPlayerCountInput() {\n const playerCountInput = document.getElementById('playerCount');\n if (playerCountInput) {\n playerCountInput.addEventListener('change', PageMtgGame.updatePlayerSetup);\n }\n }\n hookupStartGameButton() {\n const startGameButton = document.querySelector('.setup-section .setup-actions .btn-tcg');\n if (startGameButton) {\n startGameButton.addEventListener('click', () => { this.startGame(); });\n }\n }\n /*\n hookupCommanderDeathIncrementButtons() {\n const commanderDeathIncremementButtons = document.querySelectorAll('#players-grid .player-card .commander-deaths .death-btn');\n if (commanderDeathIncremementButtons) {\n commanderDeathIncremementButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGame.changeCommanderDeaths);\n });\n }\n }\n hookupEliminateCommanderButtons() {\n const eliminateCommanderButtons = document.querySelector('#players-grid .player-card .eliminate-btn');\n if (eliminateCommanderButtons) {\n eliminateCommanderButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGame.toggleEliminate);\n });\n }\n }\n hookupPlayerLifeIncrementButtons() {\n const playerLifeIncrementButtons = document.querySelector('#players-grid .player-card .eliminate-btn');\n if (playerLifeIncrementButtons) {\n playerLifeIncrementButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGame.changeLife);\n });\n }\n }\n hookupCommanderDamageIncrementButtons() {\n const commanderDamageIncrementButtons = document.querySelector('#players-grid .player-card .eliminate-btn');\n if (commanderDamageIncrementButtons) {\n commanderDamageIncrementButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGame.changeCommanderDamage);\n });\n }\n }\n */\n\n async loadGameFromServer() {\n console.log(\"loading game from server\");\n try {\n // Fetch players, rounds, and damage records from API\n const [playersResponse, roundsResponse, damageResponse] = await Promise.all([\n API.getGamePlayers(gameId)\n , API.getGameRounds(gameId)\n , API.getGameDamageRecords(gameId)\n ]);\n console.log({ playersResponse, damageResponse });\n\n let setupSection = document.getElementById('setupSection');\n let gameSection = document.getElementById('gameSection');\n setupSection.classList.remove('hidden');\n gameSection.classList.add('hidden');\n\n if (playersResponse.status !== 'success') {\n console.error('Failed to load players:', playersResponse.message);\n return;\n }\n\n const savedPlayers = playersResponse.data || [];\n const savedRounds = roundsResponse.status === 'success' ? (roundsResponse.data || []) : [];\n const savedDamageRecords = damageResponse.status === 'success' ? (damageResponse.data || []) : [];\n \n players = savedPlayers;\n rounds = savedRounds;\n damageRecords = savedDamageRecords;\n\n if (savedPlayers.length === 0) {\n // No players yet, show setup section\n return;\n }\n\n // Hide setup, show game\n setupSection.classList.add('hidden');\n gameSection.classList.remove('hidden');\n\n console.log({ savedPlayers, damageRecords });\n\n // Render players to DOM\n const latestRoundId = PageMtgGame.getLatestRoundId();\n const latestRound = rounds.filter(round => round[attrRoundId] == latestRoundId)[0];\n const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();\n DOM.setElementValuesCurrentAndPrevious(roundDisplayOrderLabel, latestRound[flagDisplayOrder]);\n \n this.renderPlayers();\n\n } catch (error) {\n console.error('Error loading game from server:', error);\n }\n }\n static getRoundDisplayOrderLabel() {\n return document.querySelector([\n '#gameSection'\n , ' > .'\n , flagRow\n , '.'\n , flagRound\n , ' > .'\n , flagRow\n , '.'\n , flagRound\n , ' > .'\n , flagRound\n , '.'\n , flagDisplayOrder\n , ' > span.'\n , flagRound\n , '.'\n , flagDisplayOrder\n ].join(''));\n }\n\n renderPlayers() {\n const grid = document.getElementById('playersGrid');\n grid.innerHTML = '';\n \n // let activeRoundId = PageMtgGame.getActiveRoundId();\n const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();\n const currentRoundDisplayOrder = parseInt(DOM.getElementValueCurrent(roundDisplayOrderLabel));\n let activeRound = rounds.filter(round => round[flagDisplayOrder] == currentRoundDisplayOrder)[0];\n if (activeRound == null) {\n activeRound = PageMtgGame.makeDefaultGameRound(currentRoundDisplayOrder);\n rounds.push(activeRound);\n }\n DOM.setElementValueCurrent(roundDisplayOrderLabel, activeRound[flagDisplayOrder]);\n \n const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= currentRoundDisplayOrder)\n .map(round => round[attrRoundId]);\n players.forEach((player, index) => {\n // Build display name: prefer user_name + deck_name, fallback to player name\n const playerId = player[attrPlayerId];\n let displayName = PageMtgGame.makePlayerDisplayName(playerId, index);\n let damagePlayerPairs = [...players, { [attrPlayerId]: null }];\n let maxCommanderDamageReceived = 0;\n damagePlayerPairs.forEach(damagePlayerPair => {\n const sourceId = damagePlayerPair[attrPlayerId];\n const filteredPlayerDamages = damageRecords.filter(damage => (\n damage[attrRoundId] == activeRound[attrRoundId]\n // previousRoundIds.includes(damage[attrRoundId])\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == sourceId\n )); //[playerId] || {};\n if (filteredPlayerDamages.length == 0) {\n damageRecords.push(PageMtgGame.makeDefaultGameRoundPlayerDamage(playerId, sourceId));\n }\n maxCommanderDamageReceived = Math.max(\n maxCommanderDamageReceived\n , damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == sourceId\n && damage[attrReceivedFromCommanderPlayerId] != null\n && previousRoundIds.includes(damage[attrRoundId])\n ))\n .map(damage => damage[flagLifeLoss])\n .reduce((a, b) => a + b, 0)\n );\n });\n\n const totalDamage = damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && previousRoundIds.includes(damage[attrRoundId])\n ))\n .map(damage => damage[flagLifeLoss] - damage[flagLifeGain])\n .reduce((a, b) => a + b, 0);\n let life = startingLife - totalDamage;\n\n let isEliminatedByForce = damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && previousRoundIds.includes(damage[attrRoundId])\n ))\n .map(damage => damage[flagIsEliminated])\n .some(Boolean);\n console.log(\"renderPlayers\");\n console.log({isEliminatedByForce, player, life, maxCommanderDamageReceived});\n const isEliminated = (\n isEliminatedByForce\n || !player[flagActive]\n || life < 1\n || maxCommanderDamageReceived >= 21\n );\n\n const totalCommanderDeaths = damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n && damage[attrRoundId] == activeRound[attrRoundId]\n ))\n .map(damage => damage[flagCommanderDeaths])\n .reduce((a, b) => a + b, 0);\n const card = document.createElement('div');\n card.className = `player-card ${isEliminated ? 'eliminated' : ''}`;\n card.style.animationDelay = `${index * 0.1}s`;\n card.dataset.playerId = playerId;\n card.dataset.userName = player.user_name || '';\n card.dataset.deckName = player.deck_name || '';\n\n card.innerHTML = `\n
\n
\n
${displayName}
\n
\n Commander Deaths:\n
\n \n ${totalCommanderDeaths}\n \n
\n
\n
\n \n
\n\n
\n \n
${life}
\n \n
\n \n \n \n \n
\n \n
\n \n \n \n \n
\n
\n\n
\n
Commander Damage Taken
\n
\n ${PageMtgGame.renderCommanderDamageRows(\n playerId // playerId\n , player[attrDeckId] // deckId\n )}\n
\n
\n `;\n\n grid.appendChild(card);\n });\n\n this.reorderPlayerCards();\n\n PageMtgGame.renderCommanderDamageLog();\n\n // Hookup all event handlers\n this.hookupGameRoundEvents();\n this.hookupPlayerCardEvents();\n }\n static renderCommanderDamageLog() {\n const currentRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n\n const damageTableBody = document.querySelector('.' + flagDamageLog + '.' + flagContainer + ' table tbody');\n damageTableBody.innerHTML = '';\n \n const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= currentRoundDisplayOrder)\n .map(round => round[attrRoundId]);\n let newTableBodyHtml = '';\n damageRecords.forEach((damage) => {\n if (\n damage[flagActive]\n && (\n damage[flagCommanderDeaths] > 0\n || damage[flagLifeGain] != 0\n || damage[flagLifeLoss] != 0\n || damage[flagIsEliminated]\n )\n // && rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0][flagDisplayOrder] <= currentRoundDisplayOrder\n && previousRoundIds.includes(damage[attrRoundId])\n ) {\n debugger;\n let round = rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0];\n let player = players.filter(p => p[attrPlayerId] == damage[attrPlayerId])[0];\n let receivedFromPlayer = (damage[attrReceivedFromCommanderPlayerId] == null) ? { [flagName]: ''} : players.filter(p => p[attrPlayerId] == damage[attrReceivedFromCommanderPlayerId])[0];\n newTableBodyHtml += `\n \n ${round[flagDisplayOrder]}\n ${player[flagName]}\n ${receivedFromPlayer[flagName]}\n ${damage[flagLifeGain]}\n ${damage[flagLifeLoss]}\n ${damage[flagCommanderDeaths]}\n ${damage[flagIsEliminated]}\n \n `;\n }\n });\n damageTableBody.innerHTML = newTableBodyHtml;\n }\n static makeDefaultGameRoundPlayerDamage(playerId, receivedFromCommanderPlayerId) {\n let roundId = PageMtgGame.getActiveRoundId();\n return {\n [attrDamageId]: -1 - damageRecords.length\n , [attrRoundId]: roundId\n , [attrPlayerId]: playerId\n , [attrReceivedFromCommanderPlayerId]: receivedFromCommanderPlayerId\n , [flagLifeGain]: 0\n , [flagLifeLoss]: 0\n , [flagCommanderDeaths]: 0\n , [flagIsEliminated]: false\n , [flagActive]: true\n };\n }\n static getLatestRoundId() {\n let roundId = -1;\n if (rounds.length > 0) {\n const highestRoundDisplayOrder = rounds.map(round => { return round[flagDisplayOrder]; })\n .reduce((acc, cur) => Math.max(acc, cur), 0);\n const filteredRounds = rounds.filter(round => round[flagDisplayOrder] == highestRoundDisplayOrder);\n if (filteredRounds.length > 0) {\n roundId = filteredRounds[0][attrRoundId];\n }\n console.log({ \"method\": \"getLatestRoundId\", highestRoundDisplayOrder, filteredRounds, roundId });\n }\n return roundId;\n }\n static getActiveRoundDisplayOrder() {\n const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();\n return parseInt(DOM.getElementValueCurrent(roundDisplayOrderLabel));\n }\n static getActiveRoundId() {\n const currentRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n let roundId = 0;\n if (rounds.length > 0) {\n let filteredRounds = rounds.filter(round => round[flagDisplayOrder] == currentRoundDisplayOrder);\n if (filteredRounds.length > 0) roundId = filteredRounds[0][attrRoundId];\n console.log({ \"method\": \"getActiveRoundId\", filteredRounds, roundId });\n }\n return roundId;\n }\n static makePlayerDisplayName(playerId, index) {\n if (playerId == null) {\n return `Player ${index + 1}`;\n }\n const player = players.filter(player => player[attrPlayerId] == playerId)[0];\n const deckId = player[attrDeckId];\n const deck = (deckId == null) ? null : decks.filter(deck => deck[attrDeckId] == deckId)[0];\n const user = (playerId == null) ? null : users[player[attrUserId]];\n return player[flagName] || `${(user == null) ? 'Error' : user[flagName]} - ${(deck == null) ? 'Error' : deck[flagName]}`;\n }\n static renderCommanderDamageRows(playerId) {\n const activeRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= activeRoundDisplayOrder)\n .map(round => round[attrRoundId]);\n return players\n .filter(otherPlayer => otherPlayer[attrPlayerId] !== playerId)\n .map(otherPlayer => {\n const sourceId = otherPlayer[attrPlayerId];\n let otherPlayerDisplayName = PageMtgGame.makePlayerDisplayName(sourceId);\n const totalDamage = damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == sourceId\n // && damage[attrRoundId] == roundId\n && previousRoundIds.includes(damage[attrRoundId])\n ))\n .map(damage => damage[flagLifeLoss])\n .reduce((acc, curr) => acc + curr, 0);\n const isLethal = (totalDamage >= 21);\n\n return `\n
\n from ${otherPlayerDisplayName}\n
\n \n \n ${totalDamage}\n \n
\n
\n `;\n })\n .join('');\n }\n\n hookupGameRoundEvents() {\n let incrementRoundButtonSelector = '#gameSection .' + flagRow + '.' + flagRound + ' button.' + flagRoundDisplayOrderButton;\n Events.hookupEventHandler(\"click\", incrementRoundButtonSelector, (event, button) => {\n const amount = button.classList.contains(flagRoundDisplayOrderPlus) ? 1 : -1;\n const roundDisplayOrderButtonContainer = button.parentElement;\n const roundDisplayOrderLabel = roundDisplayOrderButtonContainer.querySelector('span.' + flagRound + '.' + flagDisplayOrder);\n const currentRoundDisplayOrder = parseInt(DOM.getElementValueCurrent(roundDisplayOrderLabel));\n const newDisplayOrder = currentRoundDisplayOrder + amount;\n DOM.setElementValueCurrent(roundDisplayOrderLabel, newDisplayOrder);\n DOM.isElementDirty(roundDisplayOrderLabel);\n this.updateAndToggleShowButtonsSaveCancel();\n this.renderPlayers();\n });\n }\n static makeDefaultGameRound(displayOrder) {\n const newDisplayOrder = (displayOrder != null) ? displayOrder : 1 + Math.max(rounds.map(round => round[flagDisplayOrder]));\n return {\n [attrRoundId]: -newDisplayOrder\n , [attrGameId]: gameId\n , [flagNotes]: null\n , [flagDisplayOrder]: newDisplayOrder\n , [flagActive]: true\n };\n }\n hookupPlayerCardEvents() {\n // Life gain buttons\n let lifeGainButtonSelector = '.life-gain-btn';\n Events.hookupEventHandler(\"click\", lifeGainButtonSelector, (event, button) => {\n debugger;\n const playerId = parseInt(button.dataset.playerId);\n const amount = parseInt(button.dataset.amount);\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damage => (\n damage[attrRoundId] == activeRoundId\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n ));\n this.changeLife(\n playerId // playerId\n , amount // amount\n , true // isLifeGainNotLoss\n , true // updateDamage\n , damageIndex // damageIndex\n );\n });\n\n // Life loss buttons\n let lifeLossButtonSelector = '.life-loss-btn';\n Events.hookupEventHandler(\"click\", lifeLossButtonSelector, (event, button) => {\n const playerId = parseInt(button.dataset.playerId);\n const amount = parseInt(button.dataset.amount);\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damage => (\n damage[attrRoundId] == activeRoundId\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n ));\n this.changeLife(\n playerId // playerId\n , amount // amount\n , false // isLifeGainNotLoss\n , true // updateDamage\n , damageIndex // damageIndex\n );\n });\n\n // Commander death buttons\n let commanderDeathButtonSelector = '.death-btn';\n Events.hookupEventHandler(\"click\", commanderDeathButtonSelector, (event, button) => {\n const playerId = parseInt(button.dataset.playerId);\n const isMinusButton = button.classList.contains('death-minus');\n const amount = (isMinusButton) ? -1 : 1;\n this.changeCommanderDeaths(playerId, amount);\n });\n\n // Commander damage buttons\n let commmanderDamageButtonSelector = '.damage-btn';\n Events.hookupEventHandler(\"click\", commmanderDamageButtonSelector, (event, button) => {\n const playerId = parseInt(button.dataset.playerId);\n const sourceId = parseInt(button.dataset.sourceId);\n const isMinusButton = button.classList.contains('damage-minus');\n const amount = (isMinusButton) ? -1 : 1;\n this.changeCommanderDamage(playerId, sourceId, amount);\n });\n\n // Eliminate buttons\n let eliminatePlayerButtonSelector = '.eliminate-btn';\n Events.hookupEventHandler(\"click\", eliminatePlayerButtonSelector, (event, button) => {\n const playerId = parseInt(button.dataset.playerId);\n this.toggleEliminate(playerId);\n });\n }\n\n changeLife(playerId, amount, isLifeGainNotLoss = false, updateDamage = false, damageIndex = null) {\n const card = document.querySelector(`.player-card[data-player-id=\"${playerId}\"]`);\n // if (!card || card.classList.contains('eliminated')) return;\n\n const lifeInput = card.querySelector(`.life-value[data-player-id=\"${playerId}\"]`);\n const lifeDisplay = card.querySelector(`.life-display[data-player-id=\"${playerId}\"]`);\n\n const currentLife = parseInt(lifeInput.value) || 0;\n const newLife = currentLife + amount * ((isLifeGainNotLoss) ? 1 : -1);\n\n DOM.setElementAttributeValueCurrent(lifeDisplay, newLife);\n DOM.isElementDirty(lifeDisplay);\n lifeInput.value = newLife;\n lifeDisplay.textContent = newLife;\n\n if (updateDamage) {\n let fieldFlag = (isLifeGainNotLoss) ? flagLifeGain : flagLifeLoss;\n damageRecords[damageIndex][fieldFlag] += amount;\n }\n\n PageMtgGame.renderCommanderDamageLog();\n\n // PageMtgGame.debouncedSave();\n this.updateAndToggleShowButtonsSaveCancel();\n }\n\n changeCommanderDamage(playerId, sourceId, amount) {\n const card = document.querySelector(`.player-card[data-player-id=\"${playerId}\"]`);\n // if (!card || card.classList.contains('eliminated')) return;\n\n const damageInput = card.querySelector(`.damage-value[data-player-id=\"${playerId}\"][data-source-id=\"${sourceId}\"]`);\n const damageDisplay = card.querySelector(`.damage-display[data-player-id=\"${playerId}\"][data-source-id=\"${sourceId}\"]`);\n\n const currentDamage = parseInt(damageInput.value) || 0;\n const newDamage = Math.max(0, currentDamage + amount);\n amount = newDamage - currentDamage;\n DOM.setElementAttributeValueCurrent(damageDisplay, newDamage);\n DOM.isElementDirty(damageDisplay);\n damageInput.value = newDamage;\n damageDisplay.textContent = newDamage;\n\n // Update lethal class\n if (newDamage >= 21) {\n damageDisplay.classList.add('lethal');\n } else {\n damageDisplay.classList.remove('lethal');\n }\n\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damageRecord => (\n damageRecord[attrRoundId] == activeRoundId\n && damageRecord[attrPlayerId] == playerId\n && damageRecord[attrReceivedFromCommanderPlayerId] == sourceId\n ));\n damageRecords[damageIndex][flagLifeLoss] += amount;\n \n let isLifeGainNotLoss = false;\n this.changeLife(\n playerId // playerId\n , -amount // amount\n , isLifeGainNotLoss // isLifeGainNotLoss\n , false // updateDamage\n , damageIndex // damageIndex\n );\n // PageMtgGame.debouncedSave();\n }\n\n changeCommanderDeaths(playerId, amount) {\n const card = document.querySelector(`.player-card[data-player-id=\"${playerId}\"]`);\n // if (!card || card.classList.contains('eliminated')) return;\n\n const deathDisplay = card.querySelector(`.death-display[data-player-id=\"${playerId}\"]`);\n const currentDeaths = parseInt(deathDisplay.textContent) || 0;\n const newDeaths = Math.max(0, currentDeaths + amount);\n\n deathDisplay.textContent = newDeaths;\n DOM.setElementAttributeValueCurrent(deathDisplay, newDeaths);\n DOM.isElementDirty(deathDisplay);\n\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damage => (\n damage[attrRoundId] == activeRoundId\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n ));\n damageRecords[damageIndex][flagCommanderDeaths] = newDeaths;\n\n PageMtgGame.renderCommanderDamageLog();\n\n // PageMtgGame.debouncedSave();\n this.updateAndToggleShowButtonsSaveCancel();\n }\n\n toggleEliminate(playerId) {\n const card = document.querySelector(`.player-card[data-player-id=\"${playerId}\"]`);\n if (!card) return;\n\n const eliminateBtn = card.querySelector(`.eliminate-btn[data-player-id=\"${playerId}\"]`);\n const wasEliminated = card.classList.contains('eliminated');\n\n if (wasEliminated) {\n card.classList.remove('eliminated');\n eliminateBtn.textContent = 'Eliminate';\n } else {\n card.classList.add('eliminated');\n eliminateBtn.textContent = 'Revive';\n }\n const isEliminated = card.classList.contains('eliminated');\n\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damage => (\n damage[attrRoundId] == activeRoundId\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n ));\n damageRecords[damageIndex][flagIsEliminated] = isEliminated;\n\n DOM.setElementAttributeValueCurrent(eliminateBtn, isEliminated);\n DOM.isElementDirty(eliminateBtn);\n\n this.reorderPlayerCards();\n PageMtgGame.renderCommanderDamageLog();\n\n // PageMtgGame.debouncedSave();\n this.updateAndToggleShowButtonsSaveCancel();\n }\n reorderPlayerCards() {\n let playerGrid = document.getElementById('playersGrid');\n let currentPlayerCards = playerGrid.querySelectorAll('.player-card');\n let newPlayerCards = [];\n let playerCardMetas = [];\n currentPlayerCards.forEach((playerCard, index) => {\n newPlayerCards.push(playerCard.cloneNode(true));\n playerCardMetas.push({\n [flagIsEliminated]: playerCard.classList.contains(flagIsEliminated)\n , [attrPlayerId]: playerCard.dataset[\"playerId\"]\n , [flagDisplayOrder]: index\n });\n });\n let activeRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n let newPlayerGridInnerHTML = '';\n let playerIdA, playerIdB, isEliminatedAsIntA, isEliminatedAsIntB, playerA, playerB, indexPlayerCard;\n playerCardMetas.sort((a, b) => {\n playerIdA = a[attrPlayerId];\n playerIdB = b[attrPlayerId];\n isEliminatedAsIntA = PageMtgGame.isPlayerEliminated(playerIdA, activeRoundDisplayOrder) ? 1 : 0;\n isEliminatedAsIntB = PageMtgGame.isPlayerEliminated(playerIdB, activeRoundDisplayOrder) ? 1 : 0;\n playerA = players.filter(p => p[attrPlayerId] == playerIdA)[0];\n playerB = players.filter(p => p[attrPlayerId] == playerIdB)[0];\n return (\n players.length * isEliminatedAsIntA\n + playerA[flagDisplayOrder]\n ) - (\n players.length * isEliminatedAsIntB\n + playerB[flagDisplayOrder]\n );\n }).forEach((playerCardMeta) => {\n indexPlayerCard = playerCardMeta[flagDisplayOrder];\n newPlayerGridInnerHTML += newPlayerCards[indexPlayerCard].outerHTML;\n });\n\n playerGrid.innerHTML = newPlayerGridInnerHTML;\n\n playerGrid.querySelectorAll('.' + flagInitialised).forEach((initialisedElement) => {\n initialisedElement.classList.remove(flagInitialised);\n });\n\n this.hookupPlayerCardEvents();\n }\n static isPlayerEliminated(playerId, roundDisplayOrder = null) {\n if (roundDisplayOrder == null) roundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n const filteredRoundIds = rounds.filter(round => round[flagDisplayOrder] <= roundDisplayOrder)\n .map(round => round[attrRoundId]);\n let hasDamageWithIsEliminated = damageRecords.filter(damage => (\n // damage[attrRoundId] <= roundDisplayOrder\n filteredRoundIds.includes(damage[attrRoundId])\n && damage[attrPlayerId] == playerId\n && damage[flagIsEliminated]\n )).length > 0;\n let damageFromOtherPlayers = {};\n let otherPlayerId;\n damageRecords.filter(damage => (\n // damage[attrRoundId] <= roundId\n filteredRoundIds.includes(damage[attrRoundId])\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] != null\n ))\n .forEach((damage) => {\n otherPlayerId = damage[attrReceivedFromCommanderPlayerId];\n damageFromOtherPlayers[otherPlayerId] = \n damage[flagLifeLoss]\n + ((damageFromOtherPlayers[otherPlayerId] == null) ? 0 : damageFromOtherPlayers[otherPlayerId]);\n });\n let maxDamageFromOtherCommander = Object.keys(damageFromOtherPlayers)\n .map((playerId) => damageFromOtherPlayers[playerId])\n .reduce((acc, cur) => Math.max(acc, cur), 0);\n let totalDamageTaken = damageRecords.filter(damage => (\n // damage[attrRoundId] <= roundId\n filteredRoundIds.includes(damage[attrRoundId])\n && damage[attrPlayerId] == playerId\n ))\n .map((damage) => damage[flagLifeLoss] - damage[flagLifeGain])\n .reduce((a, b) => a + b, 0);\n console.log({ roundDisplayOrder, filteredRoundIds, hasDamageWithIsEliminated, maxDamageFromOtherCommander, totalDamageTaken });\n return (\n hasDamageWithIsEliminated\n || maxDamageFromOtherCommander >= 21\n || totalDamageTaken >= startingLife\n );\n }\n\n static updatePlayerSetup() {\n const playerCountInput = document.getElementById('playerCount');\n if (!playerCountInput) return;\n\n const playerCount = parseInt(playerCountInput.value);\n const grid = document.getElementById('playerSetupGrid');\n if (!grid) return;\n\n grid.innerHTML = '';\n const wrapperTemplate = document.getElementById(playerSetupWrapperTemplateId);\n let player, wrapper, wrapperHeading, userDdl, deckDdl, nameInput;\n for (let i = 0; i < playerCount; i++) {\n if (i < players.length) {\n player = players[i];\n }\n else {\n player = PageMtgGame.makeDefaultGamePlayer();\n players.push(player);\n }\n wrapper = wrapperTemplate.cloneNode(true);\n wrapper.removeAttribute(\"id\");\n wrapper.setAttribute(flagDisplayOrder, i + 1);\n wrapper.classList.remove(flagIsCollapsed);\n wrapperHeading = wrapper.querySelector('label');\n wrapperHeading.innerText = 'Player ' + (i + 1);\n userDdl = wrapper.querySelector('.playerUser select');\n DOM.setElementValuesCurrentAndPrevious(userDdl, player[attrUserId]);\n deckDdl = wrapper.querySelector('.playerDeck select');\n DOM.setElementValuesCurrentAndPrevious(deckDdl, player[attrDeckId]);\n nameInput = wrapper.querySelector('.playerName input');\n DOM.setElementValuesCurrentAndPrevious(nameInput, player[flagName]);\n console.log('player: ', player);\n grid.appendChild(wrapper);\n }\n }\n static makeDefaultGamePlayer() {\n return {\n [attrPlayerId]: -players.length\n , [attrGameId]: gameId\n , [attrUserId]: user[attrUserId]\n , [attrDeckId]: 0\n , [flagName]: \"\"\n , [flagNotes]: null\n , [flagDisplayOrder]: players.length\n , [flagActive]: true\n };\n }\n\n async startGame() {\n const playerCountInput = document.getElementById('playerCount');\n if (!playerCountInput) return;\n\n const playerCount = parseInt(playerCountInput.value);\n const playersToSave = [];\n\n let playerSetupWrapper, playerId, player, userDdl, userId, deckDdl, deckId, nameInput, name;\n for (let i = 0; i < playerCount; i++) {\n playerSetupWrapper = document.querySelector('.player-name-input-wrapper[' + flagDisplayOrder + '=\"' + (i + 1) + '\"]');\n userDdl = playerSetupWrapper.querySelector('.playerUser select');\n deckDdl = playerSetupWrapper.querySelector('.playerDeck select');\n nameInput = playerSetupWrapper.querySelector('.playerName input');\n \n userId = DOM.getElementValueCurrent(userDdl);\n deckId = DOM.getElementValueCurrent(deckDdl);\n name = nameInput ? nameInput.value.trim() || null : null; // `Player ${i + 1}` : `Player ${i + 1}`;\n\n playerId = playerSetupWrapper.getAttribute(attrPlayerId);\n player = players.filter(p => p[attrPlayerId] == playerId)[0];\n playersToSave.push({\n ...player\n , [attrGameId]: gameId\n , [attrUserId]: userId\n , [attrDeckId]: deckId\n , [flagName]: name\n , [flagDisplayOrder]: i + 1\n , [flagActive]: true\n });\n }\n\n // Save players to server\n const comment = 'Save players';\n const self = this;\n API.saveGamePlayers(playersToSave, null, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n self.leave();\n window.location.reload();\n }\n else {\n console.error('Failed to save players:', data[flagMessage]);\n PageMtgGame.showError('An error occurred while creating the game');\n }\n })\n .catch(error => {\n console.error('Error creating game:', error);\n PageMtgGame.showError('An error occurred while creating the game');\n })\n .finally(() => {\n });\n }\n\n static resetGame() {\n if (confirm('Are you sure you want to start a new game? Current game will be lost.')) {\n localStorage.removeItem(`mtgGame_${gameId}`);\n window.location.href = hashPageGames;\n }\n }\n\n async saveGame() {\n /*\n const gameState = {\n [flagPlayer]: players\n , [flagRound]: rounds\n , [flagDamage]: damageRecords\n };\n if (gameState[flagPlayer].length > 0) {\n localStorage.setItem(`mtgGame_${gameId}`, JSON.stringify(gameState));\n PageMtgGame.showSaveIndicator();\n }\n */\n const comment = 'Save player damage';\n const self = this;\n API.saveGameRoundPlayerDamages(rounds, damageRecords, null, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n self.leave();\n window.location.reload();\n }\n else {\n console.error('Failed to save player damages:', data[flagMessage]);\n PageMtgGame.showError('An error occurred while saving player damages');\n }\n })\n .catch(error => {\n console.error('Error saving player damages:', error);\n PageMtgGame.showError('An error occurred while saving player damages');\n })\n .finally(() => {\n });\n }\n /*\n static debouncedSave() {\n clearTimeout(PageMtgGame._saveTimeout);\n PageMtgGame._saveTimeout = setTimeout(() => PageMtgGame.saveGame(), 500);\n }\n\n static showSaveIndicator() {\n const indicator = document.getElementById('saveIndicator');\n if (indicator) {\n indicator.classList.add('show');\n setTimeout(() => {\n indicator.classList.remove('show');\n }, 2000);\n }\n }\n */\n saveRecordsTableDirty() {\n this.saveGame();\n }\n static showError(message) {\n // Check if there's an overlay error element\n const errorOverlay = document.getElementById('overlayError');\n if (errorOverlay) {\n const errorLabel = errorOverlay.querySelector('.error-message, #labelError');\n if (errorLabel) {\n errorLabel.textContent = message;\n }\n errorOverlay.classList.remove('hidden');\n errorOverlay.style.display = 'flex';\n } else {\n // Fallback to alert\n alert(message);\n }\n }\n\n leave() {\n super.leave();\n }\n}\n\n// Static timeout reference for debouncing\nPageMtgGame._saveTimeout = null;\n","\nimport API from \"../../api.js\";\nimport TableBasePage from \"../base_table.js\";\nimport Utils from \"../../lib/utils.js\";\n\nexport default class PageMtgGames extends TableBasePage {\n static hash = hashPageMtgGames;\n static attrIdRowObject = attrGameId;\n callSaveTableContent = API.saveGame;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n hookupFilters() {\n /*\n this.sharedHookupFilters();\n this.hookupFilterActive();\n */\n }\n\n loadRowTable(rowJson) {\n if (rowJson == null) return;\n if (_verbose) { Utils.consoleLogIfNotProductionEnvironment(\"applying data row: \", rowJson); }\n }\n getJsonRow(row) {\n return;\n }\n initialiseRowNew(tbody, row) {\n }\n postInitialiseRowNewCallback(tbody) {\n }\n\n hookupTableMain() {\n super.hookupTableMain();\n // this.hookupTableMainRows();\n this.hookupTcgGames();\n // PageMtgGames.hideNewGameForm();\n }\n hookupTcgGames() {\n console.log(\"hookupTableMain PageMtgGames\");\n // Initialize form submission\n const newGameForm = document.getElementById('newGameForm');\n if (newGameForm) {\n newGameForm.addEventListener('submit', this.handleNewGameSubmit.bind(this)); // () => { this.handleNewGameSubmit.bind(this); });\n }\n\n // Initialize filter form\n const filterForm = document.getElementById('formFilters');\n if (filterForm) {\n filterForm.addEventListener('submit', PageMtgGames.handleFilterSubmit);\n }\n\n // Close modal on escape key\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape') {\n PageMtgGames.hideNewGameForm();\n }\n });\n\n // Close modal on backdrop click\n const modal = document.getElementById('newGameModal');\n if (modal) {\n modal.addEventListener('click', function(e) {\n if (e.target === modal) {\n PageMtgGames.hideNewGameForm();\n }\n });\n }\n\n // Button onclicks\n const newGameButton = document.getElementById('btnNewGame');\n if (newGameButton) {\n newGameButton.addEventListener('click', PageMtgGames.showNewGameForm);\n }\n const cancelNewGameButtons = document.querySelectorAll(\n '#newGameForm .form-actions .btn-tcg.btn-tcg-secondary'\n + ','\n + '#newGameModal .modal-content .modal-header .modal-close'\n );\n if (cancelNewGameButtons.length > 0) {\n cancelNewGameButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGames.hideNewGameForm);\n });\n }\n\n }\n static showNewGameForm() {\n const modal = document.getElementById('newGameModal');\n if (modal) {\n modal.classList.remove(flagIsCollapsed);\n document.body.style.overflow = 'hidden';\n\n // Focus on first input\n const firstInput = modal.querySelector('input, select');\n if (firstInput) {\n firstInput.focus();\n }\n }\n }\n static hideNewGameForm() {\n const modal = document.getElementById('newGameModal');\n if (modal) {\n modal.classList.add(flagIsCollapsed);\n document.body.style.overflow = '';\n\n // Reset form\n const form = document.getElementById('newGameForm');\n if (form) {\n form.reset();\n }\n }\n }\n async handleNewGameSubmit(e) {\n e.preventDefault();\n\n const form = e.target;\n const formData = new FormData(form);\n\n const gameType = formData.get('game_type');\n const gameData = {\n [attrGameId]: -1\n , [flagIsCommander]: gameType === 'commander'\n , [flagIsDraft]: gameType === 'draft'\n , [flagIsSealed]: gameType === 'sealed'\n , [flagLocationName]: formData.get(flagLocationName) || null\n , [flagNotes]: formData.get(flagNotes) || null\n , [flagStartOn]: new Date().toISOString()\n , [flagStartingLife]: formData.get(flagStartingLife) || 40\n , [flagActive]: true\n };\n\n const submitBtn = form.querySelector('button[type=\"submit\"]');\n const originalText = submitBtn.textContent;\n submitBtn.textContent = 'Creating...';\n submitBtn.disabled = true;\n\n const games = [gameData];\n const comment = 'Create new game';\n API.saveGame(games, form, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n if (_verbose) { \n Utils.consoleLogIfNotProductionEnvironment('Records saved!');\n Utils.consoleLogIfNotProductionEnvironment('Data received:', data);\n }\n const gamePageHash = `${hashPageGame}/${data[attrGameId]}`;\n let filtersJson = {};\n this.leave();\n API.goToHash(gamePageHash, filtersJson);\n }\n else {\n Utils.consoleLogIfNotProductionEnvironment(\"error: \" + data[flagMessage]);\n // OverlayError.show(data[flagMessage]);\n window.location.reload();\n }\n })\n .catch(error => {\n console.error('Error creating game:', error);\n PageMtgGames.showError('An error occurred while creating the game');\n })\n .finally(() => {\n submitBtn.textContent = originalText;\n submitBtn.disabled = false;\n });\n \n }\n static handleFilterSubmit(e) {\n // Let the form submit normally - it will reload with query params\n // You can add client-side filtering here if needed\n }\n static getCSRFToken() {\n // Try meta tag first\n const metaTag = document.querySelector('meta[name=\"csrf-token\"]');\n if (metaTag) {\n return metaTag.getAttribute('content');\n }\n\n // Try hidden input\n const hiddenInput = document.querySelector('input[name=\"csrf_token\"]');\n if (hiddenInput) {\n return hiddenInput.value;\n }\n\n // Try cookie\n const cookies = document.cookie.split(';');\n for (let cookie of cookies) {\n const [name, value] = cookie.trim().split('=');\n if (name === 'csrf_token') {\n return value;\n }\n }\n\n return '';\n }\n static showError(message) {\n // Check if there's an overlay error element\n const errorOverlay = document.getElementById('overlayError');\n if (errorOverlay) {\n const errorLabel = errorOverlay.querySelector('.error-message, #labelError');\n if (errorLabel) {\n errorLabel.textContent = message;\n }\n errorOverlay.classList.remove(flagIsCollapsed);\n errorOverlay.style.display = 'flex';\n } else {\n // Fallback to alert\n alert(message);\n }\n }\n static showSuccess(message) {\n // Could implement a toast notification here\n console.log('Success:', message);\n }\n static joinGame(gameId) {\n window.location.href = `${hashPageGame}/${gameId}`;\n }\n static async deleteGame(gameId) {\n if (!confirm('Are you sure you want to delete this game? This action cannot be undone.')) {\n return;\n }\n\n try {\n const gameData = {\n 'game_id': gameId,\n 'active': false\n };\n\n const response = await fetch(hashSaveGame, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-CSRFToken': PageMtgGames.getCSRFToken()\n },\n body: JSON.stringify({\n [flagGame]: [gameData],\n 'form-filters': {},\n 'comment': 'Game deleted'\n })\n });\n\n const result = await response.json();\n\n if (result.status === 'success') {\n // Remove the row from the table\n const row = document.querySelector(`tr[data-game-id=\"${gameId}\"]`);\n if (row) {\n row.style.animation = 'tcg-fadeOut 0.3s ease-out forwards';\n setTimeout(() => row.remove(), 300);\n }\n } else {\n PageMtgGames.showError(result.message || 'Failed to delete game');\n }\n } catch (error) {\n console.error('Error deleting game:', error);\n PageMtgGames.showError('An error occurred while deleting the game');\n }\n }\n\n toggleShowButtonsSaveCancel() {}\n leave() {\n super.leave();\n }\n}\n","\n\nimport API from \"../../api.js\";\nimport BasePage from \"../base.js\";\nimport DOM from \"../../dom.js\";\nimport Events from \"../../lib/events.js\";\n\nexport default class PageMtgHome extends BasePage {\n static hash = hashPageMtgHome;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n this.hookupTcgHome();\n }\n\n hookupTcgHome() {\n }\n\n leave() {\n super.leave();\n }\n}\n","import BasePage from \"../base.js\";\n\nexport default class PageAccessibilityReport extends BasePage {\n static hash = hashPageAccessibilityReport;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}\n","import BasePage from \"../base.js\";\n\nexport default class PageAccessibilityStatement extends BasePage {\n static hash = hashPageAccessibilityStatement;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}\n","\nimport BasePage from \"../base.js\";\n\nexport default class PageLicense extends BasePage {\n static hash = hashPageLicense;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}","\nimport BasePage from \"../base.js\";\n\nexport default class PagePrivacyPolicy extends BasePage {\n static hash = hashPagePrivacyPolicy;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}","import BasePage from \"../base.js\";\n\nexport default class PageRetentionSchedule extends BasePage {\n static hash = hashPageDataRetentionSchedule;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}\n","\n\nexport default class MixinPage {\n constructor(pageCurrent) {\n this.page = pageCurrent;\n }\n\n initialize() {\n Utils.consoleLogIfNotProductionEnvironment('hookup start for ', this.page.hash);\n this.hookupFilters();\n this.hookupLocalStorage();\n }\n hookupFilters() {\n }\n hookupLocalStorage() {\n \n }\n \n leave() {}\n}\n","\nimport MixinPage from \"./mixin.js\";\n\nexport default class TableMixinPage extends MixinPage {\n constructor(pageCurrent) {\n super(pageCurrent);\n }\n initialize() {\n super.initialize();\n this.hookupFilters();\n this.hookupTable();\n }\n hookupFilters() {\n // Implement filter-specific functionality here\n }\n hookupTable() {\n // Implement table-specific functionality here\n }\n}","\nimport API from \"../../api.js\";\nimport TableMixinPage from \"../mixin_table.js\";\nimport DOM from \"../../dom.js\";\nimport TableBasePage from \"../base_table.js\";\n\nexport default class PageUser extends TableBasePage {\n static hash = hashPageUserAccount;\n static attrIdRowObject = attrUserId;\n callSaveTableContent = API.saveUsers;\n\n constructor(router) {\n super(router);\n this.mixin = new TableMixinPage(this);\n }\n\n initialize() {\n this.sharedInitialize();\n this.hookupTableMain();\n }\n\n\n hookupFilters() {\n }\n\n loadRowTable(rowJson) {\n if (rowJson == null) return;\n if (_verbose) { Utils.consoleLogIfNotProductionEnvironment(\"applying data row: \", rowJson); }\n }\n getTableRecords(dirtyOnly = false) {\n dirtyOnly = true;\n let container = document.querySelector('.' + flagCard + '.' + flagUser);\n return [this.getJsonRow(container)];\n }\n getJsonRow(container) {\n console.log(\"getJsonRow: \", container);\n if (container == null) return;\n let inputFirstname = container.querySelector(' #' + flagFirstname);\n let inputSurname = container.querySelector(' #' + flagSurname);\n let inputEmail = container.querySelector(' #' + flagEmail);\n\n let idUser = container.getAttribute(attrUserId);\n \n let jsonRow = {\n [attrUserAuth0Id]: null\n , [flagEmail]: null\n , [flagIsEmailVerified]: null\n , [flagIsSuperUser]: null\n , [flagCanAdminUser]: null\n };\n\n jsonRow[attrUserId] = idUser;\n jsonRow[flagFirstname] = DOM.getElementAttributeValueCurrent(inputFirstname);\n jsonRow[flagSurname] = DOM.getElementAttributeValueCurrent(inputSurname);\n jsonRow[flagEmail] = DOM.getElementAttributeValueCurrent(inputEmail);\n return jsonRow;\n }\n \n initialiseRowNew(tbody, row) {\n }\n postInitialiseRowNewCallback(tbody) {\n }\n\n hookupTableMain() {\n super.hookupTableMain();\n this.hookupFieldsFirstname();\n this.hookupFieldsSurname();\n this.hookupFieldsEmail();\n }\n hookupFieldsFirstname() {\n this.hookupChangeHandlerTableCells('.' + flagCard + '.' + flagUser + ' #' + flagFirstname);\n }\n hookupFieldsSurname() {\n this.hookupChangeHandlerTableCells('.' + flagCard + '.' + flagUser + ' #' + flagSurname);\n }\n hookupFieldsEmail() {\n this.hookupChangeHandlerTableCells('.' + flagCard + '.' + flagUser + ' #' + flagEmail);\n }\n\n leave() {\n super.leave();\n }\n}\n","\nimport API from \"../../api\";\nimport TableMixinPage from \"../mixin_table\";\nimport DOM from \"../../dom\";\nimport TableBasePage from \"../base_table\";\nimport Utils from \"../../lib/utils\";\n\nexport default class PageUsers extends TableBasePage {\n static hash = hashPageUserAccounts;\n static attrIdRowObject = attrUserId;\n callSaveTableContent = API.saveUsers;\n\n constructor(router) {\n super(router);\n this.mixin = new TableMixinPage(this);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n hookupFilters() {\n this.sharedHookupFilters();\n this.hookupFilterActive();\n }\n\n loadRowTable(rowJson) {\n if (rowJson == null) return;\n if (_verbose) { Utils.consoleLogIfNotProductionEnvironment(\"applying data row: \", rowJson); }\n }\n getJsonRow(row) {\n if (row == null) return;\n let inputFirstname = row.querySelector('td.' + flagFirstname + ' .' + flagFirstname);\n let inputSurname = row.querySelector('td.' + flagSurname + ' .' + flagSurname);\n let inputNotes = row.querySelector('td.' + flagNotes + ' .' + flagNotes);\n let buttonActive = row.querySelector('td.' + flagActive + ' .' + flagActive);\n\n let jsonRow = {\n [attrUserAuth0Id]: null\n , [flagEmail]: null\n , [flagIsEmailVerified]: null\n , [flagIsSuperUser]: null\n , [flagCanAdminUser]: null\n };\n jsonRow[attrUserId] = row.getAttribute(attrUserId);\n jsonRow[flagFirstname] = DOM.getElementAttributeValueCurrent(inputFirstname);\n jsonRow[flagSurname] = DOM.getElementAttributeValueCurrent(inputSurname);\n jsonRow[flagNotes] = DOM.getElementAttributeValueCurrent(inputNotes);\n jsonRow[flagActive] = buttonActive.classList.contains(flagDelete);\n\n console.log(\"jsonRow\");\n console.log(jsonRow);\n\n return jsonRow;\n }\n \n initialiseRowNew(tbody, row) {\n \n }\n postInitialiseRowNewCallback(tbody) {\n let newRows = tbody.querySelectorAll('tr.' + flagRowNew);\n let newestRow = newRows[0];\n let clickableElementsSelector = [].join('');\n newestRow.querySelectorAll(clickableElementsSelector).forEach((clickableElement) => {\n clickableElement.click();\n });\n }\n\n hookupTableMain() {\n super.hookupTableMain();\n this.hookupFieldsFirstname();\n this.hookupFieldsSurname();\n this.hookupFieldsNotesTable();\n this.hookupFieldsActive();\n }\n hookupFieldsFirstname() {\n this.hookupChangeHandlerTableCells(flagFirstname);\n }\n hookupFieldsSurname() {\n this.hookupChangeHandlerTableCells(flagSurname);\n }\n\n leave() {\n super.leave();\n }\n}\n","\n// Pages\n// Core\n// TCG\nimport PageMtgDecks from './pages/tcg/mtg_decks.js';\nimport PageMtgGame from './pages/tcg/mtg_game.js';\nimport PageMtgGames from './pages/tcg/mtg_games.js';\nimport PageMtgHome from './pages/tcg/mtg_home.js';\n// Legal\nimport PageAccessibilityReport from './pages/legal/accessibility_report.js';\nimport PageAccessibilityStatement from './pages/legal/accessibility_statement.js';\nimport PageLicense from './pages/legal/license.js';\nimport PagePrivacyPolicy from './pages/legal/privacy_policy.js';\nimport PageRetentionSchedule from './pages/legal/retention_schedule.js';\n// User\n// import PageUserLogin from './pages/user/login.js';\n// import PageUserLogout from './pages/user/logout.js';\nimport PageUser from './pages/user/user.js';\nimport PageUsers from './pages/user/users.js';\n\nimport API from './api.js';\nimport DOM from './dom.js';\nimport Utils from './lib/utils.js';\n\n\nexport default class Router {\n constructor() {\n // Pages\n this.pages = {};\n // Core\n // TCG\n this.pages[hashPageMtgDecks] = { name: 'PageMtgDecks', module: PageMtgDecks };\n this.pages[hashPageMtgGame] = { name: 'PageMtgGame', module: PageMtgGame };\n this.pages[hashPageMtgGames] = { name: 'PageMtgGames', module: PageMtgGames };\n this.pages[hashPageMtgHome] = { name: 'PageMtgGame', module: PageMtgHome };\n // Legal\n this.pages[hashPageAccessibilityStatement] = { name: 'PageAccessibilityStatement', module: PageAccessibilityStatement };\n this.pages[hashPageDataRetentionSchedule] = { name: 'PageDataRetentionSchedule', module: PageRetentionSchedule };\n this.pages[hashPageLicense] = { name: 'PageLicense', module: PageLicense };\n this.pages[hashPagePrivacyPolicy] = { name: 'PagePrivacyPolicy', module: PagePrivacyPolicy };\n // User\n // this.pages[hashPageUserLogin] = { name: 'PageUserLogin', module: PageUserLogin }; // pathModule: './pages/user/login.js' };\n // this.pages[hashPageUserLogout] = { name: 'PageUserLogout', module: PageUserLogout }; // pathModule: './pages/user/logout.js' };\n this.pages[hashPageUserAccount] = { name: 'PageUser', module: PageUser };\n this.pages[hashPageUserAccounts] = { name: 'PageUsers', module: PageUsers };\n // Routes\n this.routes = {};\n // Core\n // TCG\n this.routes[hashPageMtgDecks] = (isPopState = false) => this.navigateToHash(hashPageMtgDecks, isPopState);\n this.routes[hashPageMtgGame] = (isPopState = false) => this.navigateToHash(hashPageMtgGame, isPopState);\n this.routes[hashPageMtgGames] = (isPopState = false) => this.navigateToHash(hashPageMtgGames, isPopState);\n this.routes[hashPageMtgHome] = (isPopState = false) => this.navigateToHash(hashPageMtgHome, isPopState);\n // Legal\n this.routes[hashPageAccessibilityStatement] = (isPopState = false) => this.navigateToHash(hashPageAccessibilityStatement, isPopState);\n this.routes[hashPageDataRetentionSchedule] = (isPopState = false) => this.navigateToHash(hashPageDataRetentionSchedule, isPopState);\n this.routes[hashPageLicense] = (isPopState = false) => this.navigateToHash(hashPageLicense, isPopState);\n this.routes[hashPagePrivacyPolicy] = (isPopState = false) => this.navigateToHash(hashPagePrivacyPolicy, isPopState);\n // User\n // this.routes[hashPageUserLogin] = (isPopState = false) => this.navigateToHash(hashPageUserLogin, isPopState);\n // this.routes[hashPageUserLogout] = (isPopState = false) => this.navigateToHash(hashPageUserLogout, isPopState);\n this.routes[hashPageUserAccount] = (isPopState = false) => this.navigateToHash(hashPageUserAccount, isPopState);\n this.routes[hashPageUserAccounts] = (isPopState = false) => this.navigateToHash(hashPageUserAccounts, isPopState);\n this.initialize();\n }\n loadPage(hashPage, isPopState = false) {\n const PageClass = this.getClassPageFromHash(hashPage);\n this.currentPage = new PageClass(this);\n this.currentPage.initialize(isPopState);\n window.addEventListener('beforeunload', () => this.currentPage.leave());\n }\n getClassPageFromHash(hashPage) {\n \n let pageJson = this.pages[hashPage];\n try {\n const module = pageJson.module;\n return module; \n }\n catch (error) {\n Utils.consoleLogIfNotProductionEnvironment(\"this.pages: \", this.pages);\n console.error('Page not found:', hashPage);\n throw error;\n }\n }\n initialize() {\n window.addEventListener('popstate', this.handlePopState.bind(this));\n }\n handlePopState(event) {\n this.loadPageCurrent();\n }\n loadPageCurrent() {\n const hashPageCurrent = DOM.getHashPageCurrent();\n this.loadPage(hashPageCurrent);\n }\n navigateToHash(hash, data = null, params = null, isPopState = false) {\n let url = API.getUrlFromHash(hash, params);\n history.pushState({data: data, params: params}, '', hash);\n API.goToUrl(url, data);\n }\n \n navigateToUrl(url, data = null, appendHistory = true) {\n // this.beforeLeave();\n if (appendHistory) history.pushState(data, '', url);\n url = API.parameteriseUrl(url, data);\n API.goToUrl(url);\n }\n\n static loadPageBodyFromResponse(response) {\n DOM.loadPageBody(response.data);\n }\n}\n\nexport const router = new Router();\n","\n'use strict';\n\nimport DOM from './dom.js';\nimport Router from './router.js';\n\n\nclass App {\n constructor() {\n this.dom = new DOM();\n this.router = new Router();\n }\n\n initialize() {\n this.setupEventListeners();\n this.start();\n }\n\n setupEventListeners() {\n // document.addEventListener('click', this.handleGlobalClick.bind(this));\n }\n\n handleGlobalClick(event) {\n }\n\n start() {\n this.initPageCurrent();\n }\n\n initPageCurrent() {\n this.router.loadPageCurrent();\n }\n \n}\n\nconst app = new App();\n\nfunction domReady(fn) {\n if (document.readyState !== 'loading') {\n fn();\n } else {\n document.addEventListener('DOMContentLoaded', fn);\n }\n}\n\ndomReady(() => {\n app.initialize();\n});\n\nwindow.app = app;\n\nexport default app;","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};"],"names":["Validation","isEmpty","object","undefined","length","isString","trim","i","isValidNumber","value","positiveOnly","isNaN","parseFloat","getDataContentType","params","data","contentType","JSON","stringify","Data","ContentType","arrayContainsItem","array","itemValue","hasItem","isJQueryElementArray","jQuery","document","querySelectorAll","is","isDate","Date","getTime","dictHasKey","d","k","areEqualDicts","dict1","dict2","keys1","Object","keys","keys2","key","imageExists","url","callback","img","Image","onload","onerror","src","toFixedOrDefault","decimalPlaces","defaultValue","toFixed","Utils","DOM","setElementAttributesValuesCurrentAndPrevious","element","setElementAttributeValueCurrent","setElementAttributeValuePrevious","setAttribute","attrValueCurrent","attrValuePrevious","setElementValuesCurrentAndPrevious","setElementValueCurrent","tagName","toUpperCase","type","checked","textContent","setElementValueCurrentIfEmpty","getElementValueCurrent","getCellFromElement","closest","getRowFromElement","flagRow","selector","getClosestParent","parentSelector","parent","parentElement","matches","convertForm2JSON","elementForm","dataForm","containersFilter","flagContainerInput","flagFilter","containerFilter","labelFilter","keyFilter","filter","indexFilter","querySelector","getAttribute","loadPageBody","contentNew","pageBody","idPageBody","innerHTML","getHashPageCurrent","hashPageCurrent","body","dataset","page","updateAndCheckIsElementDirty","isElementDirty","isDirty","handleDirtyElement","toggleElementHasClassnameFlag","flagDirty","elementHasFlag","flag","elementAlreadyHasFlag","classList","contains","add","remove","hasDirtyChildrenContainer","container","hasDirtyChildrenNotDeletedContainer","flagDelete","returnVal","flagButton","flagActive","getElementAttributeValueCurrent","flagCheckbox","flagIsChecked","getElementAttributeValuePrevious","scrollToElement","scrollTop","offset","top","isElementInContainer","containerBounds","getBoundingClientRect","elementBounds","left","height","width","alertError","errorType","errorText","alert","createOptionUnselectedProductVariation","flagProductVariationType","flagNameAttrOptionText","flagName","flagNameAttrOptionValue","attrIdProductVariationType","flagProductVariation","attrIdProductVariation","createOption","optionJson","text","option","createElement","selected","escapeHtml","div","unescapeHtml","html","innerText","API","getCsrfToken","idCSRFToken","request","hashEndpoint","method","getUrlFromHash","csrfToken","options","headers","flagCsrfToken","response","fetch","ok","Error","status","json","error","console","hash","hashPageHome","parameteriseUrl","_pathHost","URLSearchParams","toString","goToUrl","window","location","href","goToHash","loginUser","flagCallback","hashPageUserLogin","saveUsers","users","formFilters","comment","dataRequest","flagFormFilters","flagUser","flagComment","hashSaveUserUser","saveGame","game","flagGame","hashSaveGame","getGamePlayers","gameId","saveGamePlayers","players","flagPlayer","hashSaveGamePlayer","getGameRounds","getGameDamageRecords","saveGameRoundPlayerDamages","rounds","damages","flagDamage","flagRound","hashSaveGameRoundPlayerDamage","BusinessObjects","getOptionJsonFromObjectJsonAndKeys","objectJson","keyText","keyValue","valueSelected","getOptionJsonFromObjectJson","getObjectText","getListObjectsFromIdDictAndCsv","idDict","idCsv","listObjects","ids","split","id","push","Events","initialiseEventHandler","selectorElement","classInitialised","eventHandler","forEach","hookupEventHandler","eventType","flagInitialised","addEventListener","event","stopPropagation","LocalStorage","getLocalStorage","parse","localStorage","getItem","setLocalStorage","newLS","setItem","getListFromDict","dict","list","consoleLogIfNotProductionEnvironment","message","environment","is_production","log","OverlayConfirm","hookup","callbackSuccess","idOverlayConfirm","flagCancel","buttonCancel","overlay","style","visibility","flagSubmit","buttonConfirm","textarea","show","flagIsCollapsed","OverlayError","BasePage","constructor","router","title","titlePageCurrent","name","initialize","sharedInitialize","logInitialisation","hookupCommonElements","hookupLogos","hookupNavigation","hookupOverlays","flagImageLogo","flagLogo","navigateToHash","idButtonHamburger","overlayHamburger","idOverlayHamburger","flagExpanded","hookupButtonsNavUserAccount","hookupButtonsNavUserLogout","hookupButtonsNavUserLogin","hookupButtonsNav","buttonSelector","button","pageHash","flagNavUserLogin","navigator","preventDefault","leave","then","Success","Message","hookupOverlayFromId","idOverlayError","idOverlay","display","hookupButtonSave","flagContainer","flagSave","target","setLocalStoragePage","dataPage","getLocalStoragePage","toggleShowButtonsSaveCancel","buttonContainerSelector","buttonSave","idButtonSave","idButtonCancel","isDirtyFilter","idTableMain","msgError","labelError","idLabelError","TableBasePage","cursorYInitial","rowInitial","placeholder","dragSrcEl","dragSrcRow","hookupTableCellDdls","bind","isPopState","isSinglePageApp","hookupFilters","hookupButtonsSaveCancel","hookupTableMain","saveRecordsTableDirtySinglePageApp","saveRecordsTableDirty","filters","getFormFilters","filtersDefault","callFilterTableContent","sharedHookupFilters","hookupButtonApplyFilters","hookupSearchTextFilter","hookupFilterActive","filterSelector","idFormFilters","flagActiveOnly","filterActiveOld","removeAttribute","parentDiv","isChecked","filterActiveNew","filterActive","svgElement","wasChecked","handleChangeFilter","filterValuePrevious","hookupFilter","filterFlag","handler","areDirtyFilters","tbody","rows","row","dirtyInputs","dirtyInput","isDirtyLabel","initialisedElements","initialisedElement","updateAndToggleShowButtonsSaveCancel","hookupFilterIsNotEmpty","flagIsNotEmpty","idButtonApplyFilters","flagSearch","hookupFilterCommandCategory","attrIdCommandCategory","filterCommandCategory","idCommandCategory","filterCommands","commandsInCategory","command","sortedCommands","sort","a","b","localeCompare","filterCommand","flagCommand","idCommandPrevious","appendChild","dispatchEvent","Event","hookupFilterCommand","attrIdCommand","hookupFilterLocation","attrIdLocation","filtersJson","callbackLoadTableContent","table","getTableMain","bodyTable","rowsJson","flagRows","every","hasOwnProperty","display_order","loadRowTable","rowJson","getAndLoadFilteredTableContentSinglePageApp","catch","hookupButtonCancel","records","getTableRecords","formElement","idTextareaConfirm","callSaveTableContent","flagStatus","flagSuccess","_verbose","flagMessage","dirtyOnly","record","getJsonRow","handleClickAddRowTable","_rowBlank","attrIdRowObject","cloneNode","countRows","initialiseRowNew","prepend","postInitialiseRowNewCallback","cacheRowBlank","selectorRowNew","flagRowNew","rowBlankTemp","initialiseSliderDisplayOrderRowNew","slidersDisplayOrder","flagDisplayOrder","flagSlider","maxDisplayOrder","slider","Math","max","sliderDisplayOrder","hookupSlidersDisplayOrderTable","selectorDisplayOrder","hookupChangeHandlerTableCells","inputSelector","handleChangeNestedElementCellTable","input","wasDirtyParentRows","getAllIsDirtyRowsInParentTree","wasDirtyElement","isDirtyElement","cascadeChangedIsDirtyNestedElementCellTable","tr","isDirtyRow","wasDirtyRow","shift","hookupChangeHandlerTableCellsWhenNotCollapsed","hookupFieldsCodeTable","flagCode","hookupFieldsNameTable","hookupFieldsDescriptionTable","flagDescription","hookupFieldsNotesTable","flagNotes","hookupFieldsActive","flagTable","handleClickRowNew","selectorButton","selectorButtonDelete","selectorButtonUndelete","hookupButtonsRowDelete","hookupButtonsRowUndelete","changeHandler","handleClickButtonRowDelete","changeEvent","changeElement","valuePrevious","wasDirty","parentNode","removeChild","buttonAddTemplate","idContainerTemplateElements","flagAdd","buttonAdd","replaceWith","handleClickButtonRowUndelete","buttonDeleteTemplate","buttonDelete","hookupTdsAccessLevel","hookupTableCellDdlPreviews","flagAccessLevel","accessLevels","fieldFlag","optionList","cellSelector","ddlHookup","ddlSelector","handleClickTableCellDdlPreview","optionObjectList","idSelected","td","ddl","optionObjectJson","toggleColumnCollapsed","flagColumn","isCollapsed","toggleColumnHasClassnameFlag","toggleColumnHeaderCollapsed","hookupFieldsCommandCategory","idTable","flagCommandCategory","filterCommandCategories","hookupCommandCategoryDdls","handleChangeCommandCategoryDdl","ddlCategory","idCommandCategoryRowOld","getIdCommandCategoryRow","idCommandCategoryRowNew","idCommandCategoryFilter","getIdCommandCategoryFilter","tdCommand","ddlCommand","hookupFieldsCommand","parentTr","tdCommandCategory","idCommandCategoryRow","filterCommandList","handleChangeCommandDdl","idCommandNew","getIdCommandRow","commandNew","divCommandCategory","ddlCommandCategory","elementCommandCategory","commandCategoryFilter","commandFilter","valueCurrentCommandCategoryFilter","valueCurrentCommandFilter","parseInt","getHasCommandCategoryFilter","elementCommand","getIdCommandFilter","idCommand","getHasCommandFilter","idCommandFilter","columnFlag","isRequiredFlag","classnameFlag","columnTh","columnThHasFlag","toggleColumnHeaderHasClassnameFlag","areVisibleSaveCancelButtons","PageMtgDecks","hashPageMtgDecks","attrDeckId","saveDeck","newRows","newestRow","clickableElementsSelector","attrCommanderBracketId","join","clickableElement","click","hookupTableMainRows","hookupTableMainIsCommanderCheckboxes","hookupTableMainCommanderBracketPreviews","rowSelector","flagTableMain","isRowExpanded","showSection","toggleShowDeckStatisticsSection","deckId","statisticsSectionTableBody","flagStatistics","deck","decks","newStatisticRowsHtml","statistic","attrStatisticId","flagValue","flagIsCommander","commanderBrackets","PageMtgGame","hashPageMtgGame","attrGameId","hookupTcgGame","initGamePage","pageHeading","updatePlayerSetup","loadGameFromServer","hookupResetButton","hookupPlayerCountInput","hookupStartGameButton","resetGameButton","resetGame","playerCountInput","getElementById","startGameButton","startGame","playersResponse","roundsResponse","damageResponse","Promise","all","setupSection","gameSection","savedPlayers","savedRounds","savedDamageRecords","damageRecords","latestRoundId","getLatestRoundId","latestRound","round","attrRoundId","roundDisplayOrderLabel","getRoundDisplayOrderLabel","renderPlayers","grid","currentRoundDisplayOrder","activeRound","makeDefaultGameRound","previousRoundIds","map","player","index","playerId","attrPlayerId","displayName","makePlayerDisplayName","damagePlayerPairs","maxCommanderDamageReceived","damagePlayerPair","sourceId","filteredPlayerDamages","damage","attrReceivedFromCommanderPlayerId","makeDefaultGameRoundPlayerDamage","includes","flagLifeLoss","reduce","totalDamage","flagLifeGain","life","startingLife","isEliminatedByForce","flagIsEliminated","some","Boolean","isEliminated","totalCommanderDeaths","flagCommanderDeaths","card","className","animationDelay","userName","user_name","deckName","deck_name","renderCommanderDamageRows","reorderPlayerCards","renderCommanderDamageLog","hookupGameRoundEvents","hookupPlayerCardEvents","getActiveRoundDisplayOrder","damageTableBody","flagDamageLog","newTableBodyHtml","r","p","receivedFromPlayer","attrDamageId","receivedFromCommanderPlayerId","roundId","getActiveRoundId","highestRoundDisplayOrder","acc","cur","filteredRounds","user","attrUserId","activeRoundDisplayOrder","otherPlayer","otherPlayerDisplayName","curr","isLethal","incrementRoundButtonSelector","flagRoundDisplayOrderButton","amount","flagRoundDisplayOrderPlus","roundDisplayOrderButtonContainer","newDisplayOrder","displayOrder","lifeGainButtonSelector","activeRoundId","damageIndex","findIndex","changeLife","lifeLossButtonSelector","commanderDeathButtonSelector","isMinusButton","changeCommanderDeaths","commmanderDamageButtonSelector","changeCommanderDamage","eliminatePlayerButtonSelector","toggleEliminate","isLifeGainNotLoss","updateDamage","lifeInput","lifeDisplay","currentLife","newLife","damageInput","damageDisplay","currentDamage","newDamage","damageRecord","deathDisplay","currentDeaths","newDeaths","eliminateBtn","wasEliminated","playerGrid","currentPlayerCards","newPlayerCards","playerCardMetas","playerCard","newPlayerGridInnerHTML","playerIdA","playerIdB","isEliminatedAsIntA","isEliminatedAsIntB","playerA","playerB","indexPlayerCard","isPlayerEliminated","playerCardMeta","outerHTML","roundDisplayOrder","filteredRoundIds","hasDamageWithIsEliminated","damageFromOtherPlayers","otherPlayerId","maxDamageFromOtherCommander","totalDamageTaken","playerCount","wrapperTemplate","playerSetupWrapperTemplateId","wrapper","wrapperHeading","userDdl","deckDdl","nameInput","makeDefaultGamePlayer","playersToSave","playerSetupWrapper","userId","self","reload","showError","finally","confirm","removeItem","hashPageGames","errorOverlay","errorLabel","_saveTimeout","PageMtgGames","hashPageMtgGames","hookupTcgGames","newGameForm","handleNewGameSubmit","filterForm","handleFilterSubmit","e","hideNewGameForm","modal","newGameButton","showNewGameForm","cancelNewGameButtons","overflow","firstInput","focus","form","reset","formData","FormData","gameType","get","gameData","flagIsDraft","flagIsSealed","flagLocationName","flagStartOn","toISOString","flagStartingLife","submitBtn","originalText","disabled","games","gamePageHash","hashPageGame","getCSRFToken","metaTag","hiddenInput","cookies","cookie","showSuccess","joinGame","deleteGame","result","animation","setTimeout","PageMtgHome","hashPageMtgHome","hookupTcgHome","PageAccessibilityReport","hashPageAccessibilityReport","PageAccessibilityStatement","hashPageAccessibilityStatement","PageLicense","hashPageLicense","PagePrivacyPolicy","hashPagePrivacyPolicy","PageRetentionSchedule","hashPageDataRetentionSchedule","MixinPage","pageCurrent","hookupLocalStorage","TableMixinPage","hookupTable","PageUser","hashPageUserAccount","mixin","flagCard","inputFirstname","flagFirstname","inputSurname","flagSurname","inputEmail","flagEmail","idUser","jsonRow","attrUserAuth0Id","flagIsEmailVerified","flagIsSuperUser","flagCanAdminUser","hookupFieldsFirstname","hookupFieldsSurname","hookupFieldsEmail","PageUsers","hashPageUserAccounts","inputNotes","buttonActive","Router","pages","module","routes","loadPage","hashPage","PageClass","getClassPageFromHash","currentPage","pageJson","handlePopState","loadPageCurrent","history","pushState","navigateToUrl","appendHistory","loadPageBodyFromResponse","App","dom","setupEventListeners","start","handleGlobalClick","initPageCurrent","app","domReady","fn","readyState"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"js/main.bundle.js","mappings":"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","sources":["webpack://app/./static/js/lib/validation.js","webpack://app/./static/js/dom.js","webpack://app/./static/js/api.js","webpack://app/./static/js/lib/business_objects/business_objects.js","webpack://app/./static/js/lib/events.js","webpack://app/./static/js/lib/local_storage.js","webpack://app/./static/js/lib/utils.js","webpack://app/./static/js/components/common/temporary/overlay_confirm.js","webpack://app/./static/js/pages/base.js","webpack://app/./static/js/components/common/temporary/overlay_error.js","webpack://app/./static/js/pages/base_table.js","webpack://app/./static/js/pages/tcg/mtg_decks.js","webpack://app/./static/js/pages/tcg/mtg_game.js","webpack://app/./static/js/pages/tcg/mtg_games.js","webpack://app/./static/js/pages/tcg/mtg_home.js","webpack://app/./static/js/pages/legal/accessibility_report.js","webpack://app/./static/js/pages/legal/accessibility_statement.js","webpack://app/./static/js/pages/legal/license.js","webpack://app/./static/js/pages/legal/privacy_policy.js","webpack://app/./static/js/pages/legal/retention_schedule.js","webpack://app/./static/js/pages/mixin.js","webpack://app/./static/js/pages/mixin_table.js","webpack://app/./static/js/pages/user/user.js","webpack://app/./static/js/pages/user/users.js","webpack://app/./static/js/router.js","webpack://app/./static/js/app.js","webpack://app/./static/css/main.css?0a91","webpack://app/./static/css/components/button.css?0e0b","webpack://app/./static/css/components/card.css","webpack://app/./static/css/components/dialog.css","webpack://app/./static/css/components/form.css?94e1","webpack://app/./static/css/components/image.css?9f9c","webpack://app/./static/css/components/label.css?b78f","webpack://app/./static/css/components/modal.css","webpack://app/./static/css/components/navigation.css","webpack://app/./static/css/components/overlay.css?6dfd","webpack://app/./static/css/components/table.css?e553","webpack://app/./static/css/layouts/header.css?da75","webpack://app/./static/css/layouts/footer.css?65e3","webpack://app/./static/css/layouts/table-main.css?8c15","webpack://app/./static/css/lib/reset.css","webpack://app/./static/css/lib/typography.css","webpack://app/./static/css/lib/utils.css","webpack://app/./static/css/lib/variables.css","webpack://app/./static/css/themes/dark.css?0cc3"],"sourcesContent":["\nexport default class Validation {\n /*\n isNullOrWhitespace(v) {\n let txt = JSON.stringify(v).replace('/\\s\\g', '');\n return (txt == '' || 'null');\n }\n */\n\n static isEmpty(object) {\n\n let isEmpty = true;\n\n if (object !== null && object !== \"null\" && object !== undefined && object !== \"undefined\") {\n\n if (object.length == undefined) {\n isEmpty = false; // object exists but isn't a collection\n }\n else if (typeof object === \"function\") {\n isEmpty = false; // object is reference\n }\n else { // string or collection\n\n let isString = (typeof object == \"string\");\n\n if (isString) object = object.trim();\n\n if (object.length > 0) {\n\n if (isString) {\n isEmpty = false; // String greater than length 0\n }\n else {\n\n if (typeof object[0] != \"string\") {\n isEmpty = false;\n }\n else {\n for(let i = 0; i < object.length; i++) {\n if (object[i] != \"\") {\n isEmpty = false;\n break\n }\n }\n }\n }\n }\n }\n }\n\n return isEmpty;\n }\n\n static isValidNumber(value, positiveOnly) {\n return !Validation.isEmpty(value) && !isNaN(value) && (!positiveOnly || parseFloat(value) > 0);\n }\n\n static getDataContentType(params) {\n\n var data = null;\n var contentType = '';\n\n if (!Validation.isEmpty(params)) {\n\n if (typeof params === \"string\") {\n data = params;\n contentType = \"application/x-www-form-urlencoded; charset=UTF-8\";\n }\n else {\n data = JSON.stringify(params);\n contentType = \"application/json; charset=UTF-8\";\n }\n }\n\n return { Data: data, ContentType: contentType };\n }\n\n static arrayContainsItem(array, itemValue) {\n\n var hasItem = false;\n\n if (!Validation.isEmpty(array) && !Validation.isEmpty(itemValue)) {\n\n var isJQueryElementArray = array[0] instanceof jQuery;\n\n if (isJQueryElementArray) {\n\n for (let i = 0; i < array.length; i++) {\n\n if (document.querySelectorAll(array[i]).is(itemValue)) {\n hasItem = true;\n break;\n }\n }\n }\n else {\n\n var isDate = array[0] instanceof Date;\n\n if (isDate) {\n \n for (let i = 0; i < array.length; i++) {\n\n if (array[i].getTime() === itemValue.getTime()) {\n hasItem = true;\n break;\n }\n }\n }\n else {\n\n for (let i = 0; i < array.length; i++) {\n\n if (array[i] == itemValue) {\n hasItem = true;\n break;\n }\n }\n }\n }\n }\n\n return hasItem;\n }\n\n static dictHasKey(d, k) {\n return (k in d);\n }\n static areEqualDicts(dict1, dict2) {\n const keys1 = Object.keys(dict1);\n const keys2 = Object.keys(dict2);\n \n if (keys1.length !== keys2.length) {\n return false;\n }\n \n for (let key of keys1) {\n if (dict1[key] !== dict2[key]) {\n return false;\n }\n }\n \n return true;\n }\n\n static imageExists(url, callback) {\n\n var img = new Image();\n\n img.onload = function() { callback(true); };\n img.onerror = function() { callback(false); };\n img.src = url;\n }\n\n static toFixedOrDefault(value, decimalPlaces, defaultValue = null) {\n return Validation.isValidNumber(value) ? parseFloat(value).toFixed(decimalPlaces) : defaultValue;\n }\n}\n","\nimport Utils from \"./lib/utils.js\";\nimport Validation from \"./lib/validation.js\";\n\nexport default class DOM {\n static setElementAttributesValuesCurrentAndPrevious(element, data) {\n DOM.setElementAttributeValueCurrent(element, data);\n DOM.setElementAttributeValuePrevious(element, data);\n }\n static setElementAttributeValueCurrent(element, data) {\n element.setAttribute(attrValueCurrent, data);\n }\n static setElementAttributeValuePrevious(element, data) {\n element.setAttribute(attrValuePrevious, data);\n }\n static setElementValuesCurrentAndPrevious(element, data) {\n DOM.setElementValueCurrent(element, data);\n DOM.setElementAttributeValuePrevious(element, data);\n }\n static setElementValueCurrent(element, data) {\n DOM.setElementAttributeValueCurrent(element, data);\n let tagName = element.tagName.toUpperCase();\n if (element.type === \"checkbox\") {\n element.checked = data;\n }\n else if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') {\n element.value = data;\n }\n else {\n element.textContent = data;\n }\n }\n static setElementValueCurrentIfEmpty(element, data) {\n if (Validation.isEmpty(DOM.getElementValueCurrent(element))) {\n DOM.setElementValueCurrent(element, data);\n }\n }\n static getCellFromElement(element) {\n return element.closest('td');\n }\n static getRowFromElement(element, flagRow) {\n let selector = Validation.isEmpty(flagRow) ? 'tr' : 'tr.' + flagRow;\n return element.closest(selector);\n }\n static getClosestParent(element, parentSelector) {\n let parent = element.parentElement;\n while (parent) {\n if (parent.matches(parentSelector)) {\n return parent;\n }\n parent = parent.parentElement;\n }\n return null;\n }\n static convertForm2JSON(elementForm) {\n let dataForm = {};\n if (Validation.isEmpty(elementForm)) {\n return dataForm;\n }\n let containersFilter = elementForm.querySelectorAll('.' + flagContainerInput + '.' + flagFilter);\n let containerFilter, labelFilter, keyFilter, filter;\n for (let indexFilter = 0; indexFilter < containersFilter.length; indexFilter++) {\n containerFilter = containersFilter[indexFilter];\n labelFilter = containerFilter.querySelector('label');\n keyFilter = labelFilter.getAttribute('for');\n filter = containerFilter.querySelector(`#${keyFilter}`);\n dataForm[keyFilter] = DOM.getElementValueCurrent(filter);\n }\n return dataForm;\n }\n static loadPageBody(contentNew) {\n let pageBody = document.querySelector(idPageBody);\n pageBody.innerHTML = contentNew;\n }\n static getHashPageCurrent() {\n const hashPageCurrent = document.body.dataset.page;\n return hashPageCurrent;\n }\n static updateAndCheckIsElementDirty(element) {\n element.setAttribute(attrValueCurrent, DOM.getElementValueCurrent(element));\n return DOM.isElementDirty(element);\n }\n static isElementDirty(element) {\n let isDirty = element.getAttribute(attrValuePrevious) != element.getAttribute(attrValueCurrent);\n DOM.handleDirtyElement(element, isDirty);\n return isDirty;\n }\n static handleDirtyElement(element, isDirty) {\n DOM.toggleElementHasClassnameFlag(element, isDirty, flagDirty);\n }\n static toggleElementHasClassnameFlag(element, elementHasFlag, flag) {\n let elementAlreadyHasFlag = element.classList.contains(flag);\n if (elementHasFlag == elementAlreadyHasFlag) return;\n if (elementHasFlag) {\n element.classList.add(flag);\n } else {\n element.classList.remove(flag);\n }\n }\n static hasDirtyChildrenContainer(container) {\n if (container == null) return false;\n return container.querySelector('.' + flagDirty) != null;\n }\n static hasDirtyChildrenNotDeletedContainer(container) {\n if (container == null || container.classList.contains(flagDelete)) return false;\n return container.querySelector('.' + flagDirty + ':not(.' + flagDelete + ', .' + flagDelete + ' *)') != null;\n }\n static getElementValueCurrent(element) {\n let returnVal = '';\n \n if (!Validation.isEmpty(element)) {\n \n let tagName = element.tagName.toUpperCase();\n if (element.type === \"checkbox\") {\n returnVal = element.checked;\n }\n /*\n else if (element.classList.contains(flagIsDatePicker)) {\n returnVal = getDatePickerDate(element, adjust4DayLightSavings);\n }\n */\n else if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') {\n returnVal = element.value;\n }\n else if (element.classList.contains(flagButton) && element.classList.contains(flagActive)) { // tagName === 'BUTTON'\n returnVal = element.classList.contains(flagDelete);\n }\n else if (tagName === 'TD') {\n returnVal = DOM.getElementAttributeValueCurrent(element);\n }\n else if (tagName == 'SVG' && element.classList.contains(flagCheckbox)) {\n returnVal = (element.classList.contains(flagIsChecked))\n }\n else {\n returnVal = element.textContent;\n }\n }\n \n if (Validation.isEmpty(returnVal)) returnVal = '';\n \n return returnVal;\n }\n static getElementAttributeValueCurrent(element) {\n if (Validation.isEmpty(element)) return null;\n return element.getAttribute(attrValueCurrent);\n }\n static getElementAttributeValuePrevious(element) {\n if (Validation.isEmpty(element)) return null;\n return element.getAttribute(attrValuePrevious);\n }\n /* base_table.handleChangeElementCellTable\n static updateAndCheckIsTableElementDirty(element) {\n let wasDirty = DOM.isElementDirty(element);\n let row = DOM.getRowFromElement(element);\n let wasDirtyRow = DOM.hasDirtyChildrenNotDeletedContainer(row);\n let isDirty = DOM.updateAndCheckIsElementDirty(element);\n let cell = DOM.getCellFromElement(element);\n Utils.consoleLogIfNotProductionEnvironment({element, row, cell, isDirty, wasDirty});\n if (isDirty != wasDirty) {\n DOM.handleDirtyElement(cell, isDirty);\n let isDirtyRow = DOM.hasDirtyChildrenNotDeletedContainer(row);\n Utils.consoleLogIfNotProductionEnvironment({isDirtyRow, wasDirtyRow});\n if (isDirtyRow != wasDirtyRow) {\n DOM.handleDirtyElement(row, isDirtyRow);\n }\n }\n }\n */\n static scrollToElement(parent, element) {\n // REQUIRED: parent has scroll-bar\n parent.scrollTop(parent.scrollTop() + (element.offset().top - parent.offset().top));\n }\n static isElementInContainer(container, element) {\n\n if (typeof jQuery === 'function') {\n if (container instanceof jQuery) container = container[0];\n if (element instanceof jQuery) element = element[0];\n }\n\n var containerBounds = container.getBoundingClientRect();\n var elementBounds = element.getBoundingClientRect();\n\n return (\n containerBounds.top <= elementBounds.top &&\n containerBounds.left <= elementBounds.left &&\n ((elementBounds.top + elementBounds.height) <= (containerBounds.top + containerBounds.height)) &&\n ((elementBounds.left + elementBounds.width) <= (containerBounds.left + containerBounds.width))\n );\n }\n static alertError(errorType, errorText) {\n alert(errorType + '\\n' + errorText);\n }\n static createOptionUnselectedProductVariation() {\n return {\n [flagProductVariationType]: {\n [flagNameAttrOptionText]: [flagName],\n [flagNameAttrOptionValue]: [attrIdProductVariationType],\n [flagName]: 'Select Variation Type',\n [attrIdProductVariationType]: 0,\n },\n [flagProductVariation]: {\n [flagNameAttrOptionText]: [flagName],\n [flagNameAttrOptionValue]: [attrIdProductVariation],\n [flagName]: 'Select Variation',\n [attrIdProductVariation]: 0,\n },\n };\n }\n static createOption(optionJson) {\n if (Validation.isEmpty(optionJson)) optionJson = {\n text: 'Select',\n value: 0,\n };\n let option = document.createElement('option');\n option.value = optionJson.value;\n option.textContent = optionJson.text;\n option.selected = optionJson.selected;\n return option;\n }\n\n static escapeHtml(text) {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n static unescapeHtml(html) {\n const div = document.createElement('div');\n div.innerHTML = html;\n return div.textContent || div.innerText || '';\n }\n}\n","import DOM from './dom.js';\n\nexport default class API {\n \n static getCsrfToken() {\n return document.querySelector(idCSRFToken).getAttribute('content');\n }\n \n static async request(hashEndpoint, method = 'GET', data = null, params = null) {\n const url = API.getUrlFromHash(hashEndpoint, params);\n const csrfToken = API.getCsrfToken();\n const options = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n [flagCsrfToken]: csrfToken,\n }\n };\n\n if (data && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {\n data = { \n ...data, \n [flagCsrfToken]: csrfToken,\n };\n options.body = JSON.stringify(data);\n }\n\n try {\n const response = await fetch(url, options);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n return await response.json();\n } catch (error) {\n console.error('API request failed:', error);\n throw error;\n }\n }\n \n static getUrlFromHash(hash, params = null) {\n if (hash == null) hash = hashPageHome;\n let url = API.parameteriseUrl(_pathHost + hash, params);\n return url;\n }\n static parameteriseUrl(url, params) {\n if (params) {\n url += '?' + new URLSearchParams(params).toString();\n }\n return url;\n }\n static goToUrl(url) {\n window.location.href = url;\n }\n static goToHash(hash, params = null) {\n const url = API.getUrlFromHash(hash, params);\n API.goToUrl(url);\n }\n\n // specific api calls\n /* Example:\n getUsers: () => request('/users'),\n getUserById: (id) => request(`/users/${id}`),\n createUser: (userData) => request('/users', 'POST', userData),\n updateUser: (id, userData) => request(`/users/${id}`, 'PUT', userData),\n deleteUser: (id) => request(`/users/${id}`, 'DELETE'),\n */\n\n // User\n // user\n static async loginUser() {\n let callback = {};\n callback[flagCallback] = DOM.getHashPageCurrent();\n return await API.request(hashPageUserLogin, 'POST', callback);\n }\n static async saveUsers(users, formFilters, comment) {\n let dataRequest = {};\n dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n dataRequest[flagUser] = users;\n dataRequest[flagComment] = comment;\n return await API.request(hashSaveUserUser, 'POST', dataRequest);\n }\n\n // MTG Game API methods\n static async getIsGameDataOutdated(game) {\n const url = `/mtg/api/game/${game[attrGameId]}/is-outdated`;\n let dataRequest = {};\n dataRequest[flagGame] = game;\n return await API.request(url, 'POST', dataRequest);\n }\n\n static async saveGame(game, formFilters, comment) {\n let dataRequest = {};\n dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n dataRequest[flagGame] = game;\n dataRequest[flagComment] = comment;\n return await API.request(hashSaveGame, 'POST', dataRequest);\n }\n\n static async getGamePlayers(gameId) {\n const url = `/mtg/api/game/${gameId}/players`;\n return await API.request(url, 'GET');\n }\n static async saveGamePlayers(players, formFilters, comment) {\n let dataRequest = {};\n dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n dataRequest[flagPlayer] = players;\n dataRequest[flagComment] = comment;\n return await API.request(hashSaveGamePlayer, 'POST', dataRequest);\n }\n\n static async getGameRounds(gameId) {\n const url = `/mtg/api/game/${gameId}/rounds`;\n return await API.request(url, 'GET');\n }\n\n static async getGameDamageRecords(gameId) {\n const url = `/mtg/api/game/${gameId}/damage-records`;\n return await API.request(url, 'GET');\n }\n static async saveGameRoundPlayerDamages(rounds, damages, formFilters, comment) {\n let dataRequest = {};\n dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n dataRequest[flagDamage] = damages;\n dataRequest[flagRound] = rounds;\n dataRequest[flagComment] = comment;\n return await API.request(hashSaveGameRoundPlayerDamage, 'POST', dataRequest);\n }\n\n\n}\n","\nimport Utils from '../utils.js';\n\nexport default class BusinessObjects {\n static getOptionJsonFromObjectJsonAndKeys(objectJson, keyText, keyValue, valueSelected = null) {\n return {\n text: objectJson[keyText],\n value: objectJson[keyValue],\n selected: (objectJson[keyValue] == valueSelected),\n };\n }\n static getOptionJsonFromObjectJson(objectJson, valueSelected = null) {\n let keyText = objectJson[flagNameAttrOptionText];\n let keyValue = objectJson[flagNameAttrOptionValue];\n // Utils.consoleLogIfNotProductionEnvironment({objectJson, keyText, keyValue});\n return BusinessObjects.getOptionJsonFromObjectJsonAndKeys(objectJson, keyText, keyValue, valueSelected);\n }\n static getObjectText(objectJson) {\n return objectJson == null ? '' : objectJson[objectJson[flagNameAttrOptionText]];\n }\n static getListObjectsFromIdDictAndCsv(idDict, idCsv) {\n let listObjects = [];\n let ids = idCsv.split(',');\n for (let id of ids) {\n listObjects.push(idDict[id]);\n }\n return listObjects;\n }\n}","\nexport default class Events {\n static initialiseEventHandler(selectorElement, classInitialised, eventHandler) {\n document.querySelectorAll(selectorElement).forEach(function(element) {\n if (element.classList.contains(classInitialised)) return;\n eventHandler(element);\n element.classList.add(classInitialised);\n });\n }\n static hookupEventHandler(eventType, selector, callback) {\n Events.initialiseEventHandler(selector, flagInitialised, (element) => {\n element.addEventListener(eventType, (event) => {\n event.stopPropagation();\n callback(event, element);\n });\n });\n }\n}","\nimport Validation from \"./validation.js\";\n\nexport default class LocalStorage {\n/*\nfunction getPageLocalStorage(pageHash) {\n\n let ls;\n try {\n ls = JSON.parse(localStorage.getItem(pageHash));\n } catch {\n\n }\n\n if (Validation.isEmpty(ls)) return {}\n\n return ls;\n}\nfunction getPageLocalStorageCurrent() {\n\n return JSON.parse(localStorage.getItem(hashPageCurrent));\n}\n\nfunction setPageLocalStorage(pageHash, newLS) {\n\n localStorage.setItem(pageHash, JSON.stringify(newLS));\n}\n\nfunction clearPageLocalStorage(pageHash) {\n localStorage.removeItem(pageHash);\n}\n\nfunction setupPageLocalStorage(pageHash) {\n\n let ls = getPageLocalStorage(pageHash);\n\n if (Validation.isEmpty(ls)) ls = {};\n\n setPageLocalStorage(pageHash, ls);\n}\n*/\n\n static getLocalStorage(key) {\n return JSON.parse(localStorage.getItem(key));\n }\n\n static setLocalStorage(key, newLS) {\n localStorage.setItem(key, JSON.stringify(newLS));\n }\n\n/*\nfunction setupPageLocalStorageNext(pageHashNext) {\n let lsOld = getPageLocalStorage(hashPageCurrent);\n hashPageCurrent = pageHashNext;\n clearPageLocalStorage(hashPageCurrent);\n setupPageLocalStorage(hashPageCurrent);\n let lsNew = getPageLocalStorage(hashPageCurrent);\n lsNew[keyBasket] = (keyBasket in lsOld) ? lsOld[keyBasket] : {'items': []};\n setPageLocalStorage(hashPageCurrent, lsNew);\n}\n*/\n}","// Utility functions\n/*\nfunction $(selector) {\n return document.querySelector(selector);\n}\n\nfunction $$(selector) {\n return document.querySelectorAll(selector);\n}\n*/\nexport default class Utils {\n static getListFromDict(dict) {\n let list = [];\n for (let key in dict) {\n list.push(dict[key]);\n }\n return list;\n }\n static consoleLogIfNotProductionEnvironment(message) {\n if (environment.is_production != \"true\") {\n console.log(message);\n }\n }\n}","\nimport Events from \"../../../lib/events.js\";\n\nexport default class OverlayConfirm {\n static hookup(callbackSuccess) {\n Events.initialiseEventHandler(idOverlayConfirm + ' button.' + flagCancel, flagInitialised, (buttonCancel) => {\n buttonCancel.addEventListener('click', () => {\n let overlay = document.querySelector(idOverlayConfirm);\n overlay.style.visibility = 'hidden';\n });\n });\n Events.initialiseEventHandler(idOverlayConfirm + ' button.' + flagSubmit, flagInitialised, (buttonConfirm) => {\n buttonConfirm.addEventListener('click', () => {\n let overlay = document.querySelector(idOverlayConfirm);\n let textarea = overlay.querySelector('textarea');\n overlay.style.visibility = 'hidden';\n callbackSuccess(textarea.value);\n });\n });\n }\n static show() {\n let overlay = document.querySelector(idOverlayConfirm);\n overlay.classList.remove(flagIsCollapsed);\n overlay.style.visibility = 'visible';\n }\n}","\nimport BusinessObjects from \"../lib/business_objects/business_objects.js\";\nimport Events from \"../lib/events.js\";\nimport LocalStorage from \"../lib/local_storage.js\";\nimport API from \"../api.js\";\nimport DOM from \"../dom.js\";\nimport Utils from \"../lib/utils.js\";\n\nimport OverlayConfirm from \"../components/common/temporary/overlay_confirm.js\";\nimport OverlayError from \"../components/common/temporary/overlay_error.js\";\nimport Validation from \"../lib/validation.js\";\n\nexport default class BasePage {\n constructor(router) {\n if (!router) {\n throw new Error(\"Router is required\");\n }\n else {\n Utils.consoleLogIfNotProductionEnvironment(\"initialising with router: \", router);\n }\n this.router = router;\n this.title = titlePageCurrent;\n if (this.constructor === BasePage) {\n throw new Error(\"Cannot instantiate abstract class\");\n }\n \n if (!this.constructor.hash) {\n throw new Error(`Class ${this.constructor.name} must have a static hash attribute.`);\n }\n }\n\n initialize() {\n throw new Error(\"Method 'initialize()' must be implemented.\");\n }\n\n sharedInitialize() {\n this.logInitialisation();\n this.hookupCommonElements();\n }\n\n logInitialisation() {\n Utils.consoleLogIfNotProductionEnvironment('Initialising ' + this.title + ' page');\n }\n \n hookupCommonElements() {\n // hookupVideos();\n this.hookupLogos();\n this.hookupNavigation();\n this.hookupOverlays();\n }\n hookupLogos() {\n Events.hookupEventHandler(\"click\", \".\" + flagImageLogo + \",\" + \".\" + flagLogo, (event, element) => {\n Utils.consoleLogIfNotProductionEnvironment('clicking logo');\n this.router.navigateToHash(hashPageHome);\n });\n }\n /*\n hookupEventHandler(eventType, selector, callback) {\n Events.initialiseEventHandler(selector, flagInitialised, (element) => {\n element.addEventListener(eventType, (event) => {\n event.stopPropagation();\n callback(event, element);\n });\n });\n }\n */\n hookupNavigation() {\n Events.hookupEventHandler(\"click\", idButtonHamburger, (event, element) => {\n let overlayHamburger = document.querySelector(idOverlayHamburger);\n if (overlayHamburger.classList.contains(flagIsCollapsed)) {\n overlayHamburger.classList.remove(flagIsCollapsed);\n overlayHamburger.classList.add(flagExpanded);\n } else {\n overlayHamburger.classList.remove(flagExpanded);\n overlayHamburger.classList.add(flagIsCollapsed);\n }\n });\n\n this.hookupButtonsNavUserAccount();\n this.hookupButtonsNavUserLogout();\n this.hookupButtonsNavUserLogin();\n }\n hookupButtonsNav(buttonSelector) {\n Events.hookupEventHandler(\"click\", buttonSelector, (event, button) => {\n let pageHash = buttonSelector.getAttribute('href');\n this.router.navigateToHash(pageHash); \n });\n }\n hookupButtonsNavUserAccount() {\n // this.hookupButtonsNav('.' + flagNavUserAccount);\n }\n hookupButtonsNavUserLogout() {\n // this.hookupButtonsNav('.' + flagNavUserLogout);\n }\n hookupButtonsNavUserLogin() {\n Events.hookupEventHandler(\"click\", '.' + flagNavUserLogin, (event, navigator) => {\n event.preventDefault();\n event.stopPropagation();\n this.leave();\n API.loginUser()\n .then((response) => {\n if (response.Success) {\n window.location.href = response[flagCallback];\n } else {\n DOM.alertError(\"Error\", response.Message);\n }\n });\n });\n }\n\n hookupOverlays() {\n this.hookupOverlayFromId(idOverlayConfirm);\n this.hookupOverlayFromId(idOverlayError);\n }\n\n hookupOverlayFromId(idOverlay) {\n Events.initialiseEventHandler(idOverlay, flagInitialised, (overlay) => {\n overlay.querySelector('button.' + flagCancel).addEventListener(\"click\", (event) => {\n event.stopPropagation();\n overlay.style.display = 'none';\n });\n });\n }\n\n hookupButtonSave() {\n Events.initialiseEventHandler('.' + flagContainer + '.' + flagSave + '.' + flagCancel + ' button.' + flagSave, flagInitialised, (button) => {\n button.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n button = event.target;\n if (button.classList.contains(flagIsCollapsed)) return;\n Utils.consoleLogIfNotProductionEnvironment('saving page: ', this.title);\n OverlayConfirm.show();\n });\n });\n }\n\n leave() {\n Utils.consoleLogIfNotProductionEnvironment('Leaving ' + this.title + ' page');\n if (this.constructor === BasePage) {\n throw new Error(\"Must implement leave() method.\");\n }\n }\n setLocalStoragePage(dataPage) {\n LocalStorage.setLocalStorage(this.hash, dataPage);\n }\n getLocalStoragePage() {\n return LocalStorage.getLocalStorage(this.hash);\n }\n\n toggleShowButtonsSaveCancel(show, buttonContainerSelector = null) { // , buttonSave = null, buttonCancel = null\n if (Validation.isEmpty(buttonContainerSelector)) buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;\n let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);\n if (buttonSave == null) return;\n let buttonCancel = document.querySelector(buttonContainerSelector + ' ' + idButtonCancel);\n Utils.consoleLogIfNotProductionEnvironment({ show, buttonContainerSelector, buttonCancel, buttonSave });\n if (show) {\n buttonCancel.classList.remove(flagIsCollapsed);\n buttonSave.classList.remove(flagIsCollapsed);\n Utils.consoleLogIfNotProductionEnvironment('showing buttons');\n } else {\n buttonCancel.classList.add(flagIsCollapsed);\n buttonSave.classList.add(flagIsCollapsed);\n Utils.consoleLogIfNotProductionEnvironment('hiding buttons');\n }\n }\n\n static isDirtyFilter(filter) {\n let isDirty = DOM.updateAndCheckIsElementDirty(filter);\n if (isDirty) document.querySelectorAll(idTableMain + ' tbody tr').remove();\n return isDirty;\n }\n\n}","\nimport Events from \"../../../lib/events.js\";\n\nexport default class OverlayError {\n static hookup() {\n Events.initialiseEventHandler(idOverlayError + ' button.' + flagCancel, flagInitialised, (buttonCancel) => {\n buttonCancel.addEventListener('click', () => {\n let overlay = document.querySelector(idOverlayError);\n overlay.style.visibility = 'hidden';\n });\n });\n }\n static show(msgError) {\n let overlay = document.querySelector(idOverlayError);\n let labelError = overlay.querySelector(idLabelError);\n labelError.innerText = msgError;\n overlay.style.visibility = 'visible';\n }\n}","\nimport BusinessObjects from \"../lib/business_objects/business_objects.js\";\nimport Events from \"../lib/events.js\";\nimport LocalStorage from \"../lib/local_storage.js\";\nimport Validation from \"../lib/validation.js\";\nimport BasePage from \"./base.js\";\nimport API from \"../api.js\";\nimport DOM from \"../dom.js\";\nimport Utils from \"../lib/utils.js\";\n\nimport OverlayConfirm from \"../components/common/temporary/overlay_confirm.js\";\nimport OverlayError from \"../components/common/temporary/overlay_error.js\";\n\nexport default class TableBasePage extends BasePage {\n // static hash\n // static attrIdRowObject\n // callSaveTableContent\n\n constructor(router) {\n super(router);\n this.cursorYInitial = null;\n this.rowInitial = null;\n this.placeholder = null;\n this.dragSrcEl = null;\n this.dragSrcRow = null;\n\n this.hookupTableCellDdls = this.hookupTableCellDdls.bind(this);\n }\n \n initialize(isPopState = false) {\n throw new Error(\"Must implement initialize() method.\");\n }\n sharedInitialize(isPopState = false, isSinglePageApp = false) {\n if (!isPopState) {\n super.sharedInitialize();\n this.hookupFilters();\n this.hookupButtonsSaveCancel();\n this.hookupTableMain();\n OverlayConfirm.hookup(() => {\n if (isSinglePageApp) {\n this.saveRecordsTableDirtySinglePageApp();\n }\n else {\n this.saveRecordsTableDirty();\n }\n });\n } else {\n let dataPage = this.getLocalStoragePage();\n let filters = dataPage[flagFormFilters];\n let formFilters = TableBasePage.getFormFilters();\n let filtersDefault = DOM.convertForm2JSON(formFilters);\n if (!Validation.areEqualDicts(filters, filtersDefault)) {\n this.callFilterTableContent();\n }\n }\n }\n hookupFilters() {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Subclass of TableBasePage must implement method hookupFilters().\");\n }\n }\n sharedHookupFilters() {\n this.hookupButtonApplyFilters();\n this.hookupSearchTextFilter();\n }\n hookupFilterActive() {\n let filterSelector = idFormFilters + ' #' + flagActiveOnly;\n let filterActiveOld = document.querySelector(filterSelector);\n filterActiveOld.removeAttribute('id');\n let parentDiv = filterActiveOld.parentElement;\n let isChecked = (DOM.getElementAttributeValuePrevious(parentDiv) == \"True\");\n let filterActiveNew = document.querySelector(idFormFilters + ' div.' + flagActiveOnly + '.' + flagContainerInput + ' svg.' + flagActiveOnly);\n filterActiveNew.setAttribute('id', flagActiveOnly);\n if (isChecked) filterActiveNew.classList.add(flagIsChecked);\n\n Events.hookupEventHandler(\"click\", filterSelector, (event, filterActive) => {\n Utils.consoleLogIfNotProductionEnvironment({ filterActive });\n Utils.consoleLogIfNotProductionEnvironment({ [filterActive.tagName]: filterActive.tagName });\n let svgElement = (filterActive.tagName.toUpperCase() == 'SVG') ? filterActive : filterActive.parentElement;\n let wasChecked = svgElement.classList.contains(flagIsChecked);\n if (wasChecked) {\n svgElement.classList.remove(flagIsChecked);\n }\n else {\n svgElement.classList.add(flagIsChecked);\n }\n return this.handleChangeFilter(event, filterActive);\n });\n let filter = document.querySelector(filterSelector);\n let filterValuePrevious = DOM.getElementValueCurrent(filter);\n filter.setAttribute(attrValueCurrent, filterValuePrevious);\n filter.setAttribute(attrValuePrevious, filterValuePrevious);\n }\n hookupFilter(filterFlag, handler = (event, filter) => { return this.handleChangeFilter(event, filter); }) {\n let filterSelector = idFormFilters + ' #' + filterFlag;\n Events.hookupEventHandler(\"change\", filterSelector, handler);\n let filter = document.querySelector(filterSelector);\n let filterValuePrevious = DOM.getElementValueCurrent(filter);\n filter.setAttribute(attrValueCurrent, filterValuePrevious);\n filter.setAttribute(attrValuePrevious, filterValuePrevious);\n }\n handleChangeFilter(event, filter) {\n let isDirtyFilter = DOM.updateAndCheckIsElementDirty(filter);\n let formFilters = TableBasePage.getFormFilters();\n let areDirtyFilters = isDirtyFilter || DOM.hasDirtyChildrenContainer(formFilters);\n let tbody = document.querySelector(idTableMain + ' tbody');\n let rows = tbody.querySelectorAll(':scope > tr');\n rows.forEach((row) => {\n if (areDirtyFilters && !row.classList.contains(flagIsCollapsed)) row.classList.add(flagIsCollapsed);\n if (!areDirtyFilters && row.classList.contains(flagIsCollapsed)) {\n row.classList.remove(flagIsCollapsed);\n let dirtyInputs = row.querySelectorAll('input.' + flagDirty);\n dirtyInputs.forEach((dirtyInput) => {\n dirtyInput.value = DOM.getElementAttributeValueCurrent(dirtyInput);\n });\n }\n });\n if (areDirtyFilters) {\n /*\n tbody.querySelectorAll('tr').forEach((tr) => { \n if (!DOM.hasDirtyChildrenContainer(tr)) tr.remove(); \n });\n */\n tbody.innerHTML = '
Press \"Apply Filters\" to refresh the table.
' + tbody.innerHTML;\n if (!tbody.classList.contains(flagIsCollapsed)) tbody.classList.add(flagIsCollapsed);\n }\n else {\n let isDirtyLabel = tbody.querySelector(\":scope > div\");\n if (isDirtyLabel != null) isDirtyLabel.remove();\n if (tbody.classList.contains(flagIsCollapsed)) tbody.classList.remove(flagIsCollapsed);\n let initialisedElements = tbody.querySelectorAll('.' + flagInitialised);\n initialisedElements.forEach((initialisedElement) => {\n initialisedElement.classList.remove(flagInitialised);\n });\n this.hookupTableMain();\n }\n this.updateAndToggleShowButtonsSaveCancel();\n }\n hookupFilterIsNotEmpty() {\n this.hookupFilter(flagIsNotEmpty);\n }\n hookupButtonApplyFilters() {\n Events.hookupEventHandler(\"click\", idButtonApplyFilters, (event, button) => {\n event.stopPropagation();\n this.callFilterTableContent();\n });\n }\n hookupSearchTextFilter() {\n this.hookupFilter(flagSearch);\n }\n hookupFilterCommandCategory() {\n this.hookupFilter(attrIdCommandCategory, (event, filterCommandCategory) => {\n this.handleChangeFilter();\n let isDirtyFilter = filterCommandCategory.classList.contains(flagDirty);\n let idCommandCategory = DOM.getElementValueCurrent(filterCommandCategory);\n console.log(\"filter commands unsorted\");\n console.log(Utils.getListFromDict(filterCommands));\n let commandsInCategory = Utils.getListFromDict(filterCommands).filter(command => command[attrIdCommandCategory] == idCommandCategory);\n let sortedCommands = commandsInCategory.sort((a, b) => a[flagName].localeCompare(b[flagName]));\n let filterCommand = document.querySelector(idFormFilters + ' .' + flagCommand);\n let idCommandPrevious = DOM.getElementAttributeValuePrevious(filterCommand);\n filterCommand.innerHTML = '';\n let optionJson, option;\n option = DOM.createOption(null);\n filterCommand.appendChild(option);\n sortedCommands.forEach((command) => {\n optionJson = BusinessObjects.getOptionJsonFromObjectJson(command, idCommandPrevious);\n option = DOM.createOption(optionJson);\n filterCommand.appendChild(option);\n });\n filterCommand.dispatchEvent(new Event('change'));\n return isDirtyFilter;\n });\n }\n hookupFilterCommand() {\n this.hookupFilter(attrIdCommand);\n }\n hookupFilterLocation() {\n this.hookupFilter(attrIdLocation);\n }\n /*\n getAndLoadFilteredTableContent = () => {\n this.callFilterTableContent()\n .catch(error => console.error('Error:', error));\n }\n */\n static getFormFilters() {\n return document.querySelector(idFormFilters);\n }\n callFilterTableContent() {\n let formFilters = TableBasePage.getFormFilters();\n let filtersJson = DOM.convertForm2JSON(formFilters);\n Utils.consoleLogIfNotProductionEnvironment(\"callFilterTableContent\");\n Utils.consoleLogIfNotProductionEnvironment(\"formFilters\");\n Utils.consoleLogIfNotProductionEnvironment(formFilters);\n Utils.consoleLogIfNotProductionEnvironment(\"filtersJson\");\n Utils.consoleLogIfNotProductionEnvironment(filtersJson);\n this.leave();\n API.goToHash(this.constructor.hash, filtersJson);\n }\n callbackLoadTableContent(response) {\n let table = TableBasePage.getTableMain();\n let bodyTable = table.querySelector('tbody');\n bodyTable.querySelectorAll('tr').forEach(function(row) { row.remove(); });\n let rowsJson = response.data[flagRows];\n if (!Validation.isEmpty(rowsJson) && rowsJson.every(row => row.hasOwnProperty('display_order'))) {\n rowsJson = rowsJson.sort((a, b) => a.display_order - b.display_order);\n }\n rowsJson.forEach(this.loadRowTable.bind(this));\n this.hookupTableMain();\n }\n static getTableMain() {\n return document.querySelector(idTableMain);\n }\n loadRowTable(rowJson) {\n throw new Error(\"Subclass of TableBasePage must implement method loadRowTable().\");\n }\n getAndLoadFilteredTableContentSinglePageApp() {\n this.callFilterTableContent()\n .then(data => {\n Utils.consoleLogIfNotProductionEnvironment('Table data received:', data);\n this.callbackLoadTableContent(data);\n })\n .catch(error => console.error('Error:', error));\n }\n hookupButtonsSaveCancel() {\n this.hookupButtonSave();\n this.hookupButtonCancel();\n this.toggleShowButtonsSaveCancel(false);\n }\n saveRecordsTableDirty() {\n let records = this.getTableRecords(true);\n if (records.length == 0) {\n OverlayError.show('No records to save');\n return;\n }\n let formElement = TableBasePage.getFormFilters();\n let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));\n this.callSaveTableContent(records, formElement, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n if (_verbose) { \n Utils.consoleLogIfNotProductionEnvironment('Records saved!');\n Utils.consoleLogIfNotProductionEnvironment('Data received:', data);\n }\n this.callFilterTableContent();\n }\n else {\n Utils.consoleLogIfNotProductionEnvironment(\"error: \", data[flagMessage]);\n OverlayError.show(data[flagMessage]);\n }\n })\n .catch(error => console.error('Error:', error));\n }\n getTableRecords(dirtyOnly = false) {\n let records = [];\n let record;\n document.querySelectorAll(idTableMain + ' > tbody > tr').forEach((row) => {\n if (dirtyOnly && !DOM.hasDirtyChildrenContainer(row)) return;\n record = this.getJsonRow(row);\n records.push(record);\n });\n return records;\n }\n getJsonRow(row) {\n throw new Error(\"Subclass of TableBasePage must implement method getJsonRow().\");\n }\n saveRecordsTableDirtySinglePageApp() {\n let records = this.getTableRecords(true);\n if (records.length == 0) {\n OverlayError.show('No records to save');\n return;\n }\n let formElement = TableBasePage.getFormFilters();\n let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));\n this.callSaveTableContent(records, formElement, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n if (_verbose) { \n Utils.consoleLogIfNotProductionEnvironment('Records saved!');\n Utils.consoleLogIfNotProductionEnvironment('Data received:', data);\n }\n this.callbackLoadTableContent(data);\n }\n else {\n Utils.consoleLogIfNotProductionEnvironment(\"error: \", data[flagMessage]);\n OverlayError.show(data[flagMessage]);\n }\n })\n .catch(error => console.error('Error:', error));\n }\n hookupButtonCancel() {\n Events.initialiseEventHandler('.' + flagContainer + '.' + flagSave + '.' + flagCancel + ' button.' + flagCancel, flagInitialised, (button) => {\n button.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n button = event.target;\n if (button.classList.contains(flagIsCollapsed)) return;\n this.callFilterTableContent();\n });\n button.classList.add(flagIsCollapsed);\n });\n }\n handleClickAddRowTable(event, button) {\n event.stopPropagation();\n _rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - _rowBlank.getAttribute(this.constructor.attrIdRowObject));\n let tbody = document.querySelector(idTableMain + ' tbody');\n if (tbody.classList.contains(flagIsCollapsed)) return;\n let row = _rowBlank.cloneNode(true);\n row.classList.remove(flagInitialised);\n row.querySelectorAll('.' + flagInitialised).forEach(function(element) {\n element.classList.remove(flagInitialised);\n });\n let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;\n row.setAttribute(this.constructor.attrIdRowObject, -1 - countRows);\n this.initialiseRowNew(tbody, row);\n tbody.prepend(row);\n tbody.scrollTop = 0;\n this.hookupTableMain();\n this.postInitialiseRowNewCallback(tbody);\n }\n initialiseRowNew(tbody, row) {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Subclass of TableBasePage must implement method initialiseRowNew().\");\n }\n // row.classList.remove(flagRowNew);\n }\n hookupTableMain() {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Must implement hookupTableMain() method.\");\n }\n Events.initialiseEventHandler(idTableMain, flagInitialised, (table) => {\n this.cacheRowBlank();\n });\n }\n cacheRowBlank() {\n let selectorRowNew = idTableMain + ' tbody tr.' + flagRowNew;\n let rowBlankTemp = document.querySelector(selectorRowNew);\n if (rowBlankTemp == null) return;\n Utils.consoleLogIfNotProductionEnvironment(\"row blank temp: \", rowBlankTemp);\n let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;\n _rowBlank = rowBlankTemp.cloneNode(true);\n document.querySelectorAll(selectorRowNew).forEach(function(row) {\n row.remove();\n });\n _rowBlank.setAttribute(this.constructor.attrIdRowObject, -1 - countRows);\n }\n postInitialiseRowNewCallback(tbody) {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Subclass of TableBasePage must implement method postInitialiseRowNewCallback(tbody).\");\n }\n }\n initialiseSliderDisplayOrderRowNew(tbody, row) {\n // let tdSelector = ':scope > tr > td.' + flagDisplayOrder;\n // let tbody = document.querySelector('table' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody');\n let slidersDisplayOrder = tbody.querySelectorAll(':scope > tr > td.' + flagDisplayOrder + ' input.' + flagSlider);\n let maxDisplayOrder = 0;\n slidersDisplayOrder.forEach((slider) => {\n maxDisplayOrder = Math.max(maxDisplayOrder, parseFloat(DOM.getElementValueCurrent(slider)));\n });\n let sliderDisplayOrder = row.querySelector('td.' + flagDisplayOrder + ' .' + flagSlider);\n DOM.setElementValuesCurrentAndPrevious(sliderDisplayOrder, maxDisplayOrder + 1);\n }\n hookupSlidersDisplayOrderTable() {\n let selectorDisplayOrder = idTableMain + ' tbody tr td.' + flagDisplayOrder + ' input.' + flagSlider + '.' + flagDisplayOrder;\n this.hookupChangeHandlerTableCells(selectorDisplayOrder);\n }\n hookupChangeHandlerTableCells(inputSelector, handler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n Events.initialiseEventHandler(inputSelector, flagInitialised, (input) => {\n input.addEventListener(\"change\", (event) => {\n handler(event, input);\n });\n handler(null, input);\n });\n }\n handleChangeNestedElementCellTable(event, element) {\n let wasDirtyParentRows = this.getAllIsDirtyRowsInParentTree(element);\n let wasDirtyElement = element.classList.contains(flagDirty);\n let isDirtyElement = DOM.updateAndCheckIsElementDirty(element);\n // Utils.consoleLogIfNotProductionEnvironment({isDirtyElement, wasDirtyElement, wasDirtyParentRows});\n // let td = DOM.getCellFromElement(element);\n // DOM.setElementAttributeValueCurrent(td, DOM.getElementAttributeValueCurrent(element));\n if (isDirtyElement != wasDirtyElement) {\n // DOM.handleDirtyElement(td, isDirtyElement);\n this.updateAndToggleShowButtonsSaveCancel();\n this.cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows);\n }\n }\n getAllIsDirtyRowsInParentTree(element) {\n let rows = [];\n let parent = element;\n let isDirty;\n while (parent) {\n if (parent.tagName.toUpperCase() == 'TR') {\n isDirty = parent.classList.contains(flagDirty)\n rows.push(isDirty);\n }\n parent = parent.parentElement;\n }\n return rows;\n }\n cascadeChangedIsDirtyNestedElementCellTable(element, isDirtyElement, wasDirtyParentRows) {\n if (Validation.isEmpty(wasDirtyParentRows)) return;\n let tr = DOM.getRowFromElement(element);\n let isDirtyRow = isDirtyElement || DOM.hasDirtyChildrenContainer(tr);\n let wasDirtyRow = wasDirtyParentRows.shift();\n Utils.consoleLogIfNotProductionEnvironment({isDirtyRow, wasDirtyRow});\n if (isDirtyRow != wasDirtyRow) {\n DOM.handleDirtyElement(tr, isDirtyRow);\n this.updateAndToggleShowButtonsSaveCancel();\n this.cascadeChangedIsDirtyNestedElementCellTable(tr.parentElement, isDirtyRow, wasDirtyParentRows);\n }\n }\n hookupChangeHandlerTableCellsWhenNotCollapsed(inputSelector, handler = (event, element) => {\n if (!element.classList.contains(flagIsCollapsed)) this.handleChangeNestedElementCellTable(event, element);\n }) {\n Events.hookupEventHandler(\"change\", inputSelector, handler);\n }\n hookupFieldsCodeTable() {\n this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagCode + ' > .' + flagCode);\n }\n hookupFieldsNameTable() {\n this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagName + ' > .' + flagName);\n }\n hookupFieldsDescriptionTable() {\n this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagDescription + ' > .' + flagDescription);\n }\n hookupFieldsNotesTable() {\n this.hookupChangeHandlerTableCells(idTableMain + ' > tbody > tr > td.' + flagNotes + ' > .' + flagNotes);\n }\n hookupFieldsActive(flagTable = '', handleClickRowNew = (event, element) => { this.handleClickAddRowTable(event, element); }) {\n let selectorButton = 'table.table-main' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > tbody > tr > td.' + flagActive + ' .' + flagButton + '.' + flagActive;\n let selectorButtonDelete = selectorButton + '.' + flagDelete;\n let selectorButtonUndelete = selectorButton + ':not(.' + flagDelete + ')';\n Utils.consoleLogIfNotProductionEnvironment(\"hookupFieldsActive: \", selectorButtonDelete, selectorButtonUndelete);\n this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete);\n this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete);\n Events.hookupEventHandler(\n \"click\"\n , 'table.table-main' + (Validation.isEmpty(flagTable) ? '' : '.' + flagTable) + ' > thead > tr > th.' + flagActive + ' .' + flagButton + '.' + flagActive\n , (event, button) => { handleClickRowNew(event, button); }\n );\n }\n hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n Events.hookupEventHandler(\"click\", selectorButtonDelete, (event, element) => {\n this.handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });\n });\n }\n handleClickButtonRowDelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n if (element.tagName.toUpperCase() != 'SVG') element = element.parentElement;\n let valuePrevious = DOM.getElementAttributeValuePrevious(element);\n let wasDirty = element.classList.contains(flagDirty);\n let row = DOM.getRowFromElement(element);\n if (row.classList.contains(flagRowNew) && !DOM.hasDirtyChildrenContainer(row)) {\n row.parentNode.removeChild(row);\n }\n else {\n let buttonAddTemplate = document.querySelector(idContainerTemplateElements + ' .' + flagButton + '.' + flagActive + '.' + flagAdd);\n let buttonAdd = buttonAddTemplate.cloneNode(true);\n DOM.setElementAttributeValuePrevious(buttonAdd, valuePrevious);\n DOM.setElementAttributeValueCurrent(buttonAdd, false);\n if (wasDirty) buttonAdd.classList.add(flagDirty);\n element.replaceWith(buttonAdd);\n changeHandler(null, buttonAdd);\n this.hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });\n }\n this.updateAndToggleShowButtonsSaveCancel();\n }\n hookupButtonsRowUndelete(selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n Events.hookupEventHandler(\"click\", selectorButtonUndelete, (event, element) => {\n this.handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });\n });\n }\n handleClickButtonRowUndelete(event, element, selectorButtonDelete, selectorButtonUndelete, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n if (element.tagName.toUpperCase() != 'SVG') element = element.parentElement;\n let valuePrevious = DOM.getElementAttributeValuePrevious(element);\n let wasDirty = DOM.isElementDirty(element);\n let buttonDeleteTemplate = document.querySelector(idContainerTemplateElements + ' .' + flagButton + '.' + flagActive + '.' + flagDelete);\n let buttonDelete = buttonDeleteTemplate.cloneNode(true);\n DOM.setElementAttributeValuePrevious(buttonDelete, valuePrevious);\n DOM.setElementAttributeValueCurrent(buttonDelete, true);\n if (wasDirty) buttonDelete.classList.add(flagDirty);\n element.replaceWith(buttonDelete);\n changeHandler(null, buttonDelete);\n this.hookupButtonsRowDelete(selectorButtonDelete, selectorButtonUndelete, (changeEvent, changeElement) => { changeHandler(changeEvent, changeElement); });\n this.updateAndToggleShowButtonsSaveCancel();\n }\n hookupTdsAccessLevel() {\n this.hookupTableCellDdlPreviews(flagAccessLevel, Utils.getListFromDict(accessLevels));\n }\n hookupTableCellDdlPreviews(\n fieldFlag\n , optionList\n , cellSelector = null\n , ddlHookup = (ddlSelector) => { this.hookupTableCellDdls(ddlSelector); }\n , changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }\n ) {\n if (cellSelector == null) cellSelector = idTableMain + ' > tbody > tr > td.' + fieldFlag;\n Events.hookupEventHandler(\"click\", cellSelector + ' div.' + fieldFlag, (event, div) => {\n this.handleClickTableCellDdlPreview(\n event\n , div\n , fieldFlag\n , optionList\n , cellSelector\n , (ddlSelector) => { ddlHookup(\n ddlSelector\n , (event, element) => { changeHandler(event, element); }\n ); }\n );\n });\n ddlHookup(cellSelector + ' select.' + fieldFlag);\n }\n hookupTableCellDdls(ddlSelector, changeHandler = (event, element) => { this.handleChangeNestedElementCellTable(event, element); }) {\n this.hookupChangeHandlerTableCells(ddlSelector, (event, element) => { changeHandler(event, element); });\n }\n handleClickTableCellDdlPreview(event, div, fieldFlag, optionObjectList, cellSelector = null, ddlHookup = (cellSelector) => { this.hookupTableCellDdls(cellSelector); }) {\n if (Validation.isEmpty(cellSelector)) cellSelector = idTableMain + ' > tbody > tr > td.' + fieldFlag;\n let idSelected = DOM.getElementAttributeValueCurrent(div);\n let td = DOM.getCellFromElement(div);\n td.innerHTML = '';\n let ddl = document.createElement('select');\n ddl.classList.add(fieldFlag);\n DOM.setElementValuesCurrentAndPrevious(ddl, idSelected);\n let optionJson, option;\n if (_verbose) { \n Utils.consoleLogIfNotProductionEnvironment(\"click table cell ddl preview\");\n Utils.consoleLogIfNotProductionEnvironment({optionObjectList, cellSelector});\n }\n option = DOM.createOption(null);\n ddl.appendChild(option);\n optionObjectList.forEach((optionObjectJson) => {\n optionJson = BusinessObjects.getOptionJsonFromObjectJson(optionObjectJson, idSelected);\n option = DOM.createOption(optionJson);\n ddl.appendChild(option);\n });\n td.appendChild(ddl);\n let ddlSelector = cellSelector + ' select.' + fieldFlag;\n ddlHookup(ddlSelector);\n }\n /*\n hookupTableCellDDlPreviewsWhenNotCollapsed(cellSelector, optionList, ddlHookup = (event, element) => { this.hookupTableCellDdls(event, element); }) {\n Events.hookupEventHandler(\"click\", cellSelector + ' div', (event, div) => {\n this.handleClickTableCellDdlPreview(event, div, optionList, cellSelector, (event, element) => { ddlHookup(event, element); });\n });\n }\n */\n toggleColumnCollapsed(flagColumn, isCollapsed) {\n this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagIsCollapsed);\n }\n toggleColumnHeaderCollapsed(flagColumn, isCollapsed) {\n this.toggleColumnHasClassnameFlag(flagColumn, isCollapsed, flagIsCollapsed);\n }\n\n hookupFieldsCommandCategory(idTable = null) {\n if (idTable == null) idTable = idTableMain;\n this.hookupTableCellDdlPreviews(\n flagCommandCategory\n , Utils.getListFromDict(filterCommandCategories).sort((a, b) => a[flagName].localeCompare(b[flagName]))\n , idTable + ' > tbody > tr > td.' + flagCommandCategory // + ' .' + flagCommandCategory\n , (cellSelector) => { this.hookupCommandCategoryDdls(cellSelector); }\n );\n }\n hookupCommandCategoryDdls(ddlSelector) {\n this.hookupChangeHandlerTableCells(ddlSelector, (event, element) => { this.handleChangeCommandCategoryDdl(event, element); });\n }\n handleChangeCommandCategoryDdl(event, ddlCategory) {\n let row = DOM.getRowFromElement(ddlCategory);\n let idCommandCategoryRowOld = this.getIdCommandCategoryRow(row); // DOM.getElementAttributeValueCurrent(ddlCategory);\n this.handleChangeNestedElementCellTable(event, ddlCategory);\n let idCommandCategoryRowNew = this.getIdCommandCategoryRow(row); // DOM.getElementAttributeValueCurrent(ddlCategory);\n if (\n idCommandCategoryRowOld == idCommandCategoryRowNew\n || idCommandCategoryRowNew == 0\n ) return;\n console.log({ idCommandCategoryRowNew, idCommandCategoryRowOld });\n let idCommandCategoryFilter = this.getIdCommandCategoryFilter();\n let tdCommand = row.querySelector('td.' + flagCommand);\n tdCommand.dispatchEvent(new Event('click'));\n let ddlCommand = row.querySelector('td.' + flagCommand + ' select.' + flagCommand);\n ddlCommand.innerHTML = '';\n ddlCommand.appendChild(DOM.createOption(null));\n let optionJson, option;\n let commandsInCategory = Utils.getListFromDict(filterCommands).filter(command => \n (\n command[attrIdCommandCategory] == idCommandCategoryRowNew\n || idCommandCategoryRowNew == 0\n )\n && (\n command[attrIdCommandCategory] == idCommandCategoryFilter\n || idCommandCategoryFilter == 0\n )\n );\n let sortedCommands = commandsInCategory.sort((a, b) => a[flagName].localeCompare(b[flagName]));\n sortedCommands.forEach((command) => {\n optionJson = BusinessObjects.getOptionJsonFromObjectJson(command);\n option = DOM.createOption(optionJson);\n ddlCommand.appendChild(option);\n });\n this.handleChangeNestedElementCellTable(event, ddlCommand);\n }\n hookupFieldsCommand(idTable = null) {\n if (idTable == null) idTable = idTableMain;\n Events.hookupEventHandler(\"click\", idTable + ' > tbody > tr > td.' + flagCommand + ' div.' + flagCommand, (event, div) => {\n Utils.consoleLogIfNotProductionEnvironment(div);\n let parentTr = DOM.getRowFromElement(div);\n Utils.consoleLogIfNotProductionEnvironment({ div, parentTr });\n let tdCommandCategory = parentTr.querySelector('td.' + flagCommandCategory);\n let idCommandCategoryRow = this.getIdCommandCategoryRow(parentTr); // DOM.getElementAttributeValueCurrent(tdCommandCategory);\n let idCommandCategoryFilter = this.getIdCommandCategoryFilter();\n let filterCommandList = Utils.getListFromDict(filterCommands);\n let commandsInCategory = filterCommandList.filter(command => \n (\n command[attrIdCommandCategory] == idCommandCategoryRow\n || idCommandCategoryRow == 0\n )\n && (\n command[attrIdCommandCategory] == idCommandCategoryFilter\n || idCommandCategoryFilter == 0\n )\n );\n let sortedCommands = commandsInCategory.sort((a, b) => a[flagName].localeCompare(b[flagName]));\n Utils.consoleLogIfNotProductionEnvironment({ tdCommandCategory, idCommandCategoryRow, idCommandCategoryFilter, filterCommandList, commandsInCategory });\n Utils.consoleLogIfNotProductionEnvironment(filterCommandList);\n this.handleClickTableCellDdlPreview(\n event\n , div\n , flagCommand // fieldFlag\n , sortedCommands // optionList\n , idTable + ' > tbody > tr > td.' + flagCommand // cellSelector\n , (cellSelector) => { this.hookupTableCellDdls(\n cellSelector\n , (event, element) => { this.handleChangeCommandDdl(event, element); }\n ); }\n );\n });\n this.hookupTableCellDdls(\n idTable + ' > tbody > tr > td.' + flagCommand + ' select.' + flagCommand\n , (event, element) => { this.handleChangeCommandDdl(event, element); }\n );\n }\n handleChangeCommandDdl(event, ddlCommand) {\n // console.log(\"handle change command ddl\");\n let row = DOM.getRowFromElement(ddlCommand);\n this.handleChangeNestedElementCellTable(event, ddlCommand);\n let idCommandCategoryRowOld = this.getIdCommandCategoryRow(row);\n let idCommandNew = this.getIdCommandRow(row);\n let commandNew = filterCommands[idCommandNew];\n // console.log({ idCommandCategoryRowOld, commandNew });\n if (commandNew == null || idCommandCategoryRowOld == commandNew[attrIdCommandCategory]) return;\n let divCommandCategory = row.querySelector('td.' + flagCommandCategory + ' div');\n if (divCommandCategory) divCommandCategory.dispatchEvent(new Event('click'));\n let ddlCommandCategory = row.querySelector('td.' + flagCommandCategory + ' select.' + flagCommandCategory);\n DOM.setElementValueCurrent(ddlCommandCategory, commandNew[attrIdCommandCategory]);\n // console.log({ ddlCommandCategory, commandNew });\n this.handleChangeNestedElementCellTable(event, ddlCommandCategory);\n }\n getIdCommandCategoryRow(tr) {\n let elementCommandCategory = tr.querySelector('td.' + flagCommandCategory + ' .' + flagCommandCategory);\n return DOM.getElementAttributeValueCurrent(elementCommandCategory);\n }\n getIdCommandCategoryFilter() {\n let formFilters = TableBasePage.getFormFilters();\n let idCommandCategory = 0;\n if (formFilters == null) return idCommandCategory;\n let commandCategoryFilter = formFilters.querySelector('#' + attrIdCommandCategory);\n let commandFilter = formFilters.querySelector('#' + attrIdCommand);\n let valueCurrentCommandCategoryFilter = DOM.getElementAttributeValueCurrent(commandCategoryFilter);\n Utils.consoleLogIfNotProductionEnvironment({ valueCurrentCommandCategoryFilter });\n if (valueCurrentCommandCategoryFilter == \"\") {\n let valueCurrentCommandFilter = DOM.getElementAttributeValueCurrent(commandFilter);\n Utils.consoleLogIfNotProductionEnvironment({ valueCurrentCommandFilter });\n if (valueCurrentCommandFilter != \"\") {\n let command = filterCommands[valueCurrentCommandFilter];\n idCommandCategory = command[attrIdCommandCategory];\n }\n } else {\n idCommandCategory = parseInt(valueCurrentCommandCategoryFilter);\n }\n return idCommandCategory;\n }\n getHasCommandCategoryFilter() {\n let idCommandCategoryFilter = this.getIdCommandCategoryFilter();\n return !(Validation.isEmpty(idCommandCategoryFilter) || idCommandCategoryFilter == 0);\n }\n getIdCommandRow(tr) {\n let elementCommand = tr.querySelector('td.' + flagCommand + ' .' + flagCommand);\n return DOM.getElementAttributeValueCurrent(elementCommand);\n }\n getIdCommandFilter() {\n let formFilters = TableBasePage.getFormFilters();\n let commandFilter = formFilters.querySelector('#' + attrIdCommand);\n let valueCurrentCommandFilter = DOM.getElementAttributeValueCurrent(commandFilter);\n let idCommand = parseInt(valueCurrentCommandFilter);\n return idCommand;\n }\n getHasCommandFilter() {\n let idCommandFilter = this.getIdCommandFilter();\n return !(Validation.isEmpty(idCommandFilter) || idCommandFilter == 0);\n }\n /*\n createTdActive(isActive) {\n let tdActive = document.createElement(\"td\");\n tdActive.classList.add(flagActive);\n let buttonActive = document.createElement(\"button\");\n buttonActive.classList.add(flagActive);\n buttonActive.classList.add(isActive ? flagDelete : flagAdd);\n buttonActive.textContent = isActive ? 'x' : '+';\n DOM.setElementAttributesValuesCurrentAndPrevious(buttonActive, isActive);\n tdActive.appendChild(buttonActive);\n return tdActive;\n }\n */\n leave() {\n if (this.constructor === TableBasePage) {\n throw new Error(\"Must implement leave() method.\");\n }\n super.leave();\n let formFilters = TableBasePage.getFormFilters();\n let dataPage = {};\n dataPage[flagFormFilters] = DOM.convertForm2JSON(formFilters);\n this.setLocalStoragePage(dataPage);\n }\n\n toggleColumnHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) {\n let table = TableBasePage.getTableMain();\n let columnTh = table.querySelector('th.' + columnFlag);\n let columnThHasFlag = columnTh.classList.contains(classnameFlag);\n if (isRequiredFlag == columnThHasFlag) return;\n DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag);\n }\n toggleColumnHeaderHasClassnameFlag(columnFlag, isRequiredFlag, classnameFlag) {\n let table = TableBasePage.getTableMain();\n let columnTh = table.querySelector('th.' + columnFlag);\n DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag);\n }\n\n updateAndToggleShowButtonsSaveCancel() {\n // let pageBody = document.querySelector(idPageBody);\n let isDirty = DOM.hasDirtyChildrenContainer(pageBody);\n\n let buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;\n let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);\n let areVisibleSaveCancelButtons = !buttonSave.classList.contains(flagIsCollapsed);\n \n console.log({ pageBody, isDirty, areVisibleSaveCancelButtons });\n\n this.toggleShowButtonsSaveCancel(isDirty || areVisibleSaveCancelButtons);\n }\n}\n","\nimport API from \"../../api.js\";\nimport Events from \"../../lib/events.js\";\nimport TableBasePage from \"../base_table.js\";\nimport Utils from \"../../lib/utils.js\";\n\nexport default class PageMtgDecks extends TableBasePage {\n static hash = hashPageMtgDecks;\n static attrIdRowObject = attrDeckId;\n callSaveTableContent = API.saveDeck;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n hookupFilters() {\n /*\n this.sharedHookupFilters();\n this.hookupFilterActive();\n */\n }\n\n loadRowTable(rowJson) {\n if (rowJson == null) return;\n if (_verbose) { Utils.consoleLogIfNotProductionEnvironment(\"applying data row: \", rowJson); }\n }\n getJsonRow(row) {\n return;\n }\n initialiseRowNew(tbody, row) {\n }\n postInitialiseRowNewCallback(tbody) {\n let newRows = tbody.querySelectorAll('tr.' + flagRowNew);\n let newestRow = newRows[0];\n let clickableElementsSelector = [\n 'td.' + attrCommanderBracketId + ' div.' + attrCommanderBracketId\n ].join('');\n newestRow.querySelectorAll(clickableElementsSelector).forEach((clickableElement) => {\n clickableElement.click();\n });\n }\n\n hookupTableMain() {\n super.hookupTableMain();\n this.hookupTableMainRows();\n this.hookupFieldsNameTable();\n this.hookupTableMainIsCommanderCheckboxes();\n this.hookupTableMainCommanderBracketPreviews();\n this.hookupFieldsActive();\n }\n hookupTableMainRows() {\n return;\n let rowSelector = 'table.' + flagTableMain + ' tbody tr';\n Events.hookupEventHandler(\"click\", rowSelector, (event, row) => {\n let isRowExpanded = row.classList.contains(flagActive);\n let showSection;\n if (isRowExpanded) {\n showSection = false;\n PageMtgDecks.toggleShowDeckStatisticsSection(showSection);\n }\n else {\n showSection = true;\n let deckId = row.getAttribute(attrDeckId);\n let statisticsSectionTableBody = document.querySelector('table.' + flagStatistics + ' tbody');\n statisticsSectionTableBody.innerHTML = '';\n let deck = decks.filter(d => d[attrDeckId] == deckId)[0];\n if (deck[flagStatistics].length > 0) {\n let newStatisticRowsHtml = '';\n deck[flagStatistics]\n .sort((a, b) => a[flagDisplayOrder] - b[flagDisplayOrder])\n .forEach((statistic) => {\n newStatisticRowsHtml += `\n \n ${statistic[flagName]}\n ${statistic[flagValue]}\n \n `;\n });\n statisticsSectionTableBody.innerHTML = newStatisticRowsHtml;\n }\n PageMtgDecks.toggleShowDeckStatisticsSection(showSection);\n }\n });\n }\n static toggleShowDeckStatisticsSection(showSection) {\n let statisticsSectionTableBody = document.querySelector('table.' + flagStatistics + ' tbody');\n if (showSection) {\n statisticsSectionTableBody.classList.remove(flagIsCollapsed);\n }\n else {\n statisticsSectionTableBody.classList.add(flagIsCollapsed);\n }\n }\n hookupTableMainIsCommanderCheckboxes() {\n this.hookupChangeHandlerTableCells(idTableMain + ' td.' + flagIsCommander + ' .' + flagIsCommander);\n }\n hookupTableMainCommanderBracketPreviews() {\n this.hookupTableCellDdlPreviews(\n attrCommanderBracketId\n , Utils.getListFromDict(commanderBrackets)\n );\n }\n \n leave() {\n super.leave();\n }\n}\n","\n\nimport API from \"../../api.js\";\nimport TableBasePage from \"../base_table.js\";\nimport DOM from \"../../dom.js\";\nimport Events from \"../../lib/events.js\";\nimport OverlayConfirm from \"../../components/common/temporary/overlay_confirm.js\";\n\nexport default class PageMtgGame extends TableBasePage {\n static hash = hashPageMtgGame;\n static attrIdRowObject = attrGameId;\n callSaveTableContent = API.saveGame;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n this.hookupTcgGame();\n }\n hookupFilters() {\n // this.sharedHookupFilters();\n }\n callFilterTableContent() {\n window.location.reload();\n }\n loadRowTable(rowJson) {\n return;\n }\n getJsonRow(row) {\n return;\n }\n initialiseRowNew(tbody, row) {\n \n }\n postInitialiseRowNewCallback(tbody) {\n \n }\n\n hookupTableMain() {\n super.hookupTableMain();\n }\n hookupTcgGame() {\n this.initGamePage();\n let pageHeading = document.querySelector('.container.company-name .tcg-title.company-name');\n pageHeading.innerText = `MTG Game #${gameId}`;\n }\n\n initGamePage() {\n // Load existing game state from API or show setup\n PageMtgGame.updatePlayerSetup();\n if (typeof gameId !== 'undefined' && gameId) {\n this.loadGameFromServer();\n }\n /*\n else {\n PageMtgGame.updatePlayerSetup();\n }\n */\n \n PageMtgGame.hookupResetButton();\n PageMtgGame.hookupPlayerCountInput();\n this.hookupStartGameButton();\n /*\n this.hookupCommanderDeathIncrementButtons();\n this.hookupEliminateCommanderButtons();\n this.hookupPlayerLifeIncrementButtons();\n this.hookupCommanderDamageIncrementButtons();\n */\n PageMtgGame.hookupOverlayGameOutdated();\n PageMtgGame.hookupGameUpdateCheck();\n }\n static hookupResetButton() {\n const resetGameButton = document.querySelector('header.game-header .header-right .btn-tcg.btn-tcg-secondary');\n if (resetGameButton) {\n resetGameButton.addEventListener('click', PageMtgGame.resetGame);\n }\n }\n static hookupPlayerCountInput() {\n const playerCountInput = document.getElementById('playerCount');\n if (playerCountInput) {\n playerCountInput.addEventListener('change', PageMtgGame.updatePlayerSetup);\n }\n }\n hookupStartGameButton() {\n const startGameButton = document.querySelector('.setup-section .setup-actions .btn-tcg');\n if (startGameButton) {\n startGameButton.addEventListener('click', () => { this.startGame(); });\n }\n }\n /*\n hookupCommanderDeathIncrementButtons() {\n const commanderDeathIncremementButtons = document.querySelectorAll('#players-grid .player-card .commander-deaths .death-btn');\n if (commanderDeathIncremementButtons) {\n commanderDeathIncremementButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGame.changeCommanderDeaths);\n });\n }\n }\n hookupEliminateCommanderButtons() {\n const eliminateCommanderButtons = document.querySelector('#players-grid .player-card .eliminate-btn');\n if (eliminateCommanderButtons) {\n eliminateCommanderButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGame.toggleEliminate);\n });\n }\n }\n hookupPlayerLifeIncrementButtons() {\n const playerLifeIncrementButtons = document.querySelector('#players-grid .player-card .eliminate-btn');\n if (playerLifeIncrementButtons) {\n playerLifeIncrementButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGame.changeLife);\n });\n }\n }\n hookupCommanderDamageIncrementButtons() {\n const commanderDamageIncrementButtons = document.querySelector('#players-grid .player-card .eliminate-btn');\n if (commanderDamageIncrementButtons) {\n commanderDamageIncrementButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGame.changeCommanderDamage);\n });\n }\n }\n */\n static hookupGameUpdateCheck() {\n const intervalId = setInterval(async () => {\n const isGameDataOutdated = await PageMtgGame.checkLastGameUpdate();\n if (isGameDataOutdated) {\n clearInterval(intervalId);\n }\n }, 30000);\n }\n static async checkLastGameUpdate() {\n try {\n // Fetch players, rounds, and damage records from API\n const isGameDataOutdatedResponse = await API.getIsGameDataOutdated(game);\n const isGameDataOutdated = isGameDataOutdatedResponse[flagData];\n console.log({ isGameDataOutdatedResponse, isGameDataOutdated });\n\n if (isGameDataOutdated) {\n // const gameDataOutdatedLabel = document.querySelector(gameDataOutdatedLabelId);\n // gameDataOutdatedLabel.classList.remove(flagIsCollapsed);\n const pageTitleElement = document.querySelector('.topnav .tcg-title');\n pageTitleElement.classList.add(flagDirty);\n PageMtgGame.showOverlayGameOutdated();\n }\n\n return isGameDataOutdated;\n } catch (error) {\n console.error('Error checking for game update from server:', error);\n }\n }\n\n static hookupOverlayGameOutdated() {\n Events.initialiseEventHandler(idOverlayGameOutdated + ' button.' + flagCancel, flagInitialised, (buttonCancel) => {\n buttonCancel.addEventListener('click', () => {\n let overlay = document.querySelector(idOverlayGameOutdated);\n overlay.style.visibility = 'hidden';\n });\n });\n Events.initialiseEventHandler(idOverlayGameOutdated + ' button.' + flagSubmit, flagInitialised, (buttonConfirm) => {\n buttonConfirm.addEventListener('click', () => {\n let overlay = document.querySelector(idOverlayGameOutdated);\n overlay.style.visibility = 'hidden';\n window.location.reload();\n });\n });\n }\n static showOverlayGameOutdated() {\n let overlay = document.querySelector(idOverlayGameOutdated);\n overlay.classList.remove(flagIsCollapsed);\n overlay.style.visibility = 'visible';\n }\n\n async loadGameFromServer() {\n console.log(\"loading game from server\");\n try {\n // Fetch players, rounds, and damage records from API\n const [playersResponse, roundsResponse, damageResponse] = await Promise.all([\n API.getGamePlayers(gameId)\n , API.getGameRounds(gameId)\n , API.getGameDamageRecords(gameId)\n ]);\n console.log({ playersResponse, damageResponse });\n\n let setupSection = document.getElementById('setupSection');\n let gameSection = document.getElementById('gameSection');\n setupSection.classList.remove('hidden');\n gameSection.classList.add('hidden');\n\n if (playersResponse.status !== 'success') {\n console.error('Failed to load players:', playersResponse.message);\n return;\n }\n\n const savedPlayers = playersResponse.data || [];\n const savedRounds = roundsResponse.status === 'success' ? (roundsResponse.data || []) : [];\n const savedDamageRecords = damageResponse.status === 'success' ? (damageResponse.data || []) : [];\n \n players = savedPlayers;\n rounds = savedRounds;\n damageRecords = savedDamageRecords;\n\n if (savedPlayers.length === 0) {\n // No players yet, show setup section\n return;\n }\n\n // Hide setup, show game\n setupSection.classList.add('hidden');\n gameSection.classList.remove('hidden');\n\n console.log({ savedPlayers, damageRecords });\n\n // Render players to DOM\n const latestRoundId = PageMtgGame.getLatestRoundId();\n const latestRound = rounds.filter(round => round[attrRoundId] == latestRoundId)[0];\n const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();\n DOM.setElementValuesCurrentAndPrevious(roundDisplayOrderLabel, latestRound[flagDisplayOrder]);\n \n this.renderPlayers();\n\n } catch (error) {\n console.error('Error loading game from server:', error);\n }\n }\n static getRoundDisplayOrderLabel() {\n return document.querySelector([\n '#gameSection'\n , ' > .'\n , flagRow\n , '.'\n , flagRound\n , ' > .'\n , flagRow\n , '.'\n , flagRound\n , ' > .'\n , flagRound\n , '.'\n , flagDisplayOrder\n , ' > span.'\n , flagRound\n , '.'\n , flagDisplayOrder\n ].join(''));\n }\n\n renderPlayers() {\n const grid = document.getElementById('playersGrid');\n grid.innerHTML = '';\n \n // let activeRoundId = PageMtgGame.getActiveRoundId();\n const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();\n const currentRoundDisplayOrder = parseInt(DOM.getElementValueCurrent(roundDisplayOrderLabel));\n let activeRound = rounds.filter(round => round[flagDisplayOrder] == currentRoundDisplayOrder)[0];\n if (activeRound == null) {\n activeRound = PageMtgGame.makeDefaultGameRound(currentRoundDisplayOrder);\n rounds.push(activeRound);\n }\n DOM.setElementValueCurrent(roundDisplayOrderLabel, activeRound[flagDisplayOrder]);\n \n const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= currentRoundDisplayOrder)\n .map(round => round[attrRoundId]);\n players.forEach((player, index) => {\n // Build display name: prefer user_name + deck_name, fallback to player name\n const playerId = player[attrPlayerId];\n let displayName = PageMtgGame.makePlayerDisplayName(playerId, index);\n let damagePlayerPairs = [...players, { [attrPlayerId]: null }];\n let maxCommanderDamageReceived = 0;\n damagePlayerPairs.forEach(damagePlayerPair => {\n const sourceId = damagePlayerPair[attrPlayerId];\n const filteredPlayerDamages = damageRecords.filter(damage => (\n damage[attrRoundId] == activeRound[attrRoundId]\n // previousRoundIds.includes(damage[attrRoundId])\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == sourceId\n )); //[playerId] || {};\n if (filteredPlayerDamages.length == 0) {\n damageRecords.push(PageMtgGame.makeDefaultGameRoundPlayerDamage(playerId, sourceId));\n }\n maxCommanderDamageReceived = Math.max(\n maxCommanderDamageReceived\n , damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == sourceId\n && damage[attrReceivedFromCommanderPlayerId] != null\n && previousRoundIds.includes(damage[attrRoundId])\n ))\n .map(damage => damage[flagLifeLoss])\n .reduce((a, b) => a + b, 0)\n );\n });\n\n const totalDamage = damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && previousRoundIds.includes(damage[attrRoundId])\n ))\n .map(damage => damage[flagLifeLoss] - damage[flagLifeGain])\n .reduce((a, b) => a + b, 0);\n let life = game[flagStartingLife] - totalDamage;\n\n let isEliminatedByForce = damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && previousRoundIds.includes(damage[attrRoundId])\n ))\n .map(damage => damage[flagIsEliminated])\n .some(Boolean);\n console.log(\"renderPlayers\");\n console.log({isEliminatedByForce, player, life, maxCommanderDamageReceived});\n const isEliminated = (\n isEliminatedByForce\n || !player[flagActive]\n || life < 1\n || maxCommanderDamageReceived >= 21\n );\n\n const totalCommanderDeaths = damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n && damage[attrRoundId] == activeRound[attrRoundId]\n ))\n .map(damage => damage[flagCommanderDeaths])\n .reduce((a, b) => a + b, 0);\n const card = document.createElement('div');\n card.className = `player-card ${isEliminated ? 'eliminated' : ''}`;\n card.style.animationDelay = `${index * 0.1}s`;\n card.dataset.playerId = playerId;\n card.dataset.userName = player.user_name || '';\n card.dataset.deckName = player.deck_name || '';\n\n card.innerHTML = `\n
\n
\n
${displayName}
\n
\n Commander Deaths:\n
\n \n ${totalCommanderDeaths}\n \n
\n
\n
\n \n
\n\n
\n \n
${life}
\n \n
\n \n \n \n \n
\n \n
\n \n \n \n \n
\n
\n\n
\n
Commander Damage Taken
\n
\n ${PageMtgGame.renderCommanderDamageRows(\n playerId // playerId\n , player[attrDeckId] // deckId\n )}\n
\n
\n `;\n\n grid.appendChild(card);\n });\n\n this.reorderPlayerCards();\n\n PageMtgGame.renderCommanderDamageLog();\n\n // Hookup all event handlers\n this.hookupGameRoundEvents();\n this.hookupPlayerCardEvents();\n }\n static renderCommanderDamageLog() {\n const currentRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n\n const damageTableBody = document.querySelector('.' + flagDamageLog + '.' + flagContainer + ' table tbody');\n damageTableBody.innerHTML = '';\n \n const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= currentRoundDisplayOrder)\n .map(round => round[attrRoundId]);\n let newTableBodyHtml = '';\n damageRecords.forEach((damage) => {\n if (\n damage[flagActive]\n && (\n damage[flagCommanderDeaths] > 0\n || damage[flagLifeGain] != 0\n || damage[flagLifeLoss] != 0\n || damage[flagIsEliminated]\n )\n // && rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0][flagDisplayOrder] <= currentRoundDisplayOrder\n && previousRoundIds.includes(damage[attrRoundId])\n ) {\n let round = rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0];\n let player = players.filter(p => p[attrPlayerId] == damage[attrPlayerId])[0];\n let receivedFromPlayer = (damage[attrReceivedFromCommanderPlayerId] == null) ? { [flagName]: ''} : players.filter(p => p[attrPlayerId] == damage[attrReceivedFromCommanderPlayerId])[0];\n newTableBodyHtml += `\n \n ${round[flagDisplayOrder]}\n ${player[flagName]}\n ${receivedFromPlayer[flagName]}\n ${damage[flagLifeGain]}\n ${damage[flagLifeLoss]}\n ${damage[flagCommanderDeaths]}\n ${damage[flagIsEliminated]}\n \n `;\n }\n });\n damageTableBody.innerHTML = newTableBodyHtml;\n }\n static makeDefaultGameRoundPlayerDamage(playerId, receivedFromCommanderPlayerId) {\n let roundId = PageMtgGame.getActiveRoundId();\n return {\n [attrDamageId]: -1 - damageRecords.length\n , [attrRoundId]: roundId\n , [attrPlayerId]: playerId\n , [attrReceivedFromCommanderPlayerId]: receivedFromCommanderPlayerId\n , [flagLifeGain]: 0\n , [flagLifeLoss]: 0\n , [flagCommanderDeaths]: 0\n , [flagIsEliminated]: false\n , [flagActive]: true\n };\n }\n static getLatestRoundId() {\n let roundId = -1;\n if (rounds.length > 0) {\n const highestRoundDisplayOrder = rounds.map(round => { return round[flagDisplayOrder]; })\n .reduce((acc, cur) => Math.max(acc, cur), 0);\n const filteredRounds = rounds.filter(round => round[flagDisplayOrder] == highestRoundDisplayOrder);\n if (filteredRounds.length > 0) {\n roundId = filteredRounds[0][attrRoundId];\n }\n console.log({ \"method\": \"getLatestRoundId\", highestRoundDisplayOrder, filteredRounds, roundId });\n }\n return roundId;\n }\n static getActiveRoundDisplayOrder() {\n const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();\n return parseInt(DOM.getElementValueCurrent(roundDisplayOrderLabel));\n }\n static getActiveRoundId() {\n const currentRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n let roundId = 0;\n if (rounds.length > 0) {\n let filteredRounds = rounds.filter(round => round[flagDisplayOrder] == currentRoundDisplayOrder);\n if (filteredRounds.length > 0) roundId = filteredRounds[0][attrRoundId];\n console.log({ \"method\": \"getActiveRoundId\", filteredRounds, roundId });\n }\n return roundId;\n }\n static makePlayerDisplayName(playerId, index) {\n if (playerId == null) {\n return `Player ${index + 1}`;\n }\n const player = players.filter(player => player[attrPlayerId] == playerId)[0];\n const deckId = player[attrDeckId];\n const deck = (deckId == null) ? null : decks.filter(deck => deck[attrDeckId] == deckId)[0];\n const user = (playerId == null) ? null : users[player[attrUserId]];\n return player[flagName] || `${(user == null) ? 'Error' : user[flagName]} - ${(deck == null) ? 'Error' : deck[flagName]}`;\n }\n static renderCommanderDamageRows(playerId) {\n const activeRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= activeRoundDisplayOrder)\n .map(round => round[attrRoundId]);\n return players\n .filter(otherPlayer => otherPlayer[attrPlayerId] !== playerId)\n .map(otherPlayer => {\n const sourceId = otherPlayer[attrPlayerId];\n let otherPlayerDisplayName = PageMtgGame.makePlayerDisplayName(sourceId);\n const totalDamage = damageRecords.filter(damage => (\n damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == sourceId\n // && damage[attrRoundId] == roundId\n && previousRoundIds.includes(damage[attrRoundId])\n ))\n .map(damage => damage[flagLifeLoss])\n .reduce((acc, curr) => acc + curr, 0);\n const isLethal = (totalDamage >= 21);\n\n return `\n
\n from ${otherPlayerDisplayName}\n
\n \n \n ${totalDamage}\n \n
\n
\n `;\n })\n .join('');\n }\n\n hookupGameRoundEvents() {\n let incrementRoundButtonSelector = '#gameSection .' + flagRow + '.' + flagRound + ' button.' + flagRoundDisplayOrderButton;\n Events.hookupEventHandler(\"click\", incrementRoundButtonSelector, (event, button) => {\n const amount = button.classList.contains(flagRoundDisplayOrderPlus) ? 1 : -1;\n const roundDisplayOrderButtonContainer = button.parentElement;\n const roundDisplayOrderLabel = roundDisplayOrderButtonContainer.querySelector('span.' + flagRound + '.' + flagDisplayOrder);\n const currentRoundDisplayOrder = parseInt(DOM.getElementValueCurrent(roundDisplayOrderLabel));\n const newDisplayOrder = currentRoundDisplayOrder + amount;\n DOM.setElementValueCurrent(roundDisplayOrderLabel, newDisplayOrder);\n DOM.isElementDirty(roundDisplayOrderLabel);\n this.updateAndToggleShowButtonsSaveCancel();\n this.renderPlayers();\n });\n }\n static makeDefaultGameRound(displayOrder) {\n const newDisplayOrder = (displayOrder != null) ? displayOrder : 1 + Math.max(rounds.map(round => round[flagDisplayOrder]));\n return {\n [attrRoundId]: -newDisplayOrder\n , [attrGameId]: gameId\n , [flagNotes]: null\n , [flagDisplayOrder]: newDisplayOrder\n , [flagActive]: true\n };\n }\n hookupPlayerCardEvents() { \n // Life gain buttons\n let lifeGainButtonSelector = '.life-gain-btn';\n Events.hookupEventHandler(\"click\", lifeGainButtonSelector, (event, button) => {\n const playerId = parseInt(button.dataset.playerId);\n const amount = parseInt(button.dataset.amount);\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damage => (\n damage[attrRoundId] == activeRoundId\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n ));\n this.changeLife(\n playerId // playerId\n , amount // amount\n , true // isLifeGainNotLoss\n , true // updateDamage\n , damageIndex // damageIndex\n );\n });\n\n // Life loss buttons\n let lifeLossButtonSelector = '.life-loss-btn';\n Events.hookupEventHandler(\"click\", lifeLossButtonSelector, (event, button) => {\n const playerId = parseInt(button.dataset.playerId);\n const amount = parseInt(button.dataset.amount);\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damage => (\n damage[attrRoundId] == activeRoundId\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n ));\n this.changeLife(\n playerId // playerId\n , amount // amount\n , false // isLifeGainNotLoss\n , true // updateDamage\n , damageIndex // damageIndex\n );\n });\n\n // Commander death buttons\n let commanderDeathButtonSelector = '.death-btn';\n Events.hookupEventHandler(\"click\", commanderDeathButtonSelector, (event, button) => {\n const playerId = parseInt(button.dataset.playerId);\n const isMinusButton = button.classList.contains('death-minus');\n const amount = (isMinusButton) ? -1 : 1;\n this.changeCommanderDeaths(playerId, amount);\n });\n\n // Commander damage buttons\n let commmanderDamageButtonSelector = '.damage-btn';\n Events.hookupEventHandler(\"click\", commmanderDamageButtonSelector, (event, button) => {\n const playerId = parseInt(button.dataset.playerId);\n const sourceId = parseInt(button.dataset.sourceId);\n const isMinusButton = button.classList.contains('damage-minus');\n const amount = (isMinusButton) ? -1 : 1;\n this.changeCommanderDamage(playerId, sourceId, amount);\n });\n\n // Eliminate buttons\n let eliminatePlayerButtonSelector = '.eliminate-btn';\n Events.hookupEventHandler(\"click\", eliminatePlayerButtonSelector, (event, button) => {\n const playerId = parseInt(button.dataset.playerId);\n this.toggleEliminate(playerId);\n });\n }\n\n changeLife(playerId, amount, isLifeGainNotLoss = false, updateDamage = false, damageIndex = null) {\n const card = document.querySelector(`.player-card[data-player-id=\"${playerId}\"]`);\n // if (!card || card.classList.contains('eliminated')) return;\n\n const lifeInput = card.querySelector(`.life-value[data-player-id=\"${playerId}\"]`);\n const lifeDisplay = card.querySelector(`.life-display[data-player-id=\"${playerId}\"]`);\n\n const currentLife = parseInt(lifeInput.value) || 0;\n const newLife = currentLife + amount * ((isLifeGainNotLoss) ? 1 : -1);\n\n DOM.setElementAttributeValueCurrent(lifeDisplay, newLife);\n DOM.isElementDirty(lifeDisplay);\n lifeInput.value = newLife;\n lifeDisplay.textContent = newLife;\n\n if (updateDamage) {\n let fieldFlag = (isLifeGainNotLoss) ? flagLifeGain : flagLifeLoss;\n damageRecords[damageIndex][fieldFlag] += amount;\n }\n\n PageMtgGame.renderCommanderDamageLog();\n\n // PageMtgGame.debouncedSave();\n this.updateAndToggleShowButtonsSaveCancel();\n }\n\n changeCommanderDamage(playerId, sourceId, amount) {\n const card = document.querySelector(`.player-card[data-player-id=\"${playerId}\"]`);\n // if (!card || card.classList.contains('eliminated')) return;\n\n const damageInput = card.querySelector(`.damage-value[data-player-id=\"${playerId}\"][data-source-id=\"${sourceId}\"]`);\n const damageDisplay = card.querySelector(`.damage-display[data-player-id=\"${playerId}\"][data-source-id=\"${sourceId}\"]`);\n\n const currentDamage = parseInt(damageInput.value) || 0;\n const newDamage = Math.max(0, currentDamage + amount);\n amount = newDamage - currentDamage;\n DOM.setElementAttributeValueCurrent(damageDisplay, newDamage);\n DOM.isElementDirty(damageDisplay);\n damageInput.value = newDamage;\n damageDisplay.textContent = newDamage;\n\n // Update lethal class\n if (newDamage >= 21) {\n damageDisplay.classList.add('lethal');\n } else {\n damageDisplay.classList.remove('lethal');\n }\n\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damageRecord => (\n damageRecord[attrRoundId] == activeRoundId\n && damageRecord[attrPlayerId] == playerId\n && damageRecord[attrReceivedFromCommanderPlayerId] == sourceId\n ));\n damageRecords[damageIndex][flagLifeLoss] += amount;\n \n let isLifeGainNotLoss = false;\n this.changeLife(\n playerId // playerId\n , amount // amount\n , isLifeGainNotLoss // isLifeGainNotLoss\n , false // updateDamage\n , damageIndex // damageIndex\n );\n // PageMtgGame.debouncedSave();\n }\n\n changeCommanderDeaths(playerId, amount) {\n const card = document.querySelector(`.player-card[data-player-id=\"${playerId}\"]`);\n // if (!card || card.classList.contains('eliminated')) return;\n\n const deathDisplay = card.querySelector(`.death-display[data-player-id=\"${playerId}\"]`);\n const currentDeaths = parseInt(deathDisplay.textContent) || 0;\n const newDeaths = Math.max(0, currentDeaths + amount);\n\n deathDisplay.textContent = newDeaths;\n DOM.setElementAttributeValueCurrent(deathDisplay, newDeaths);\n DOM.isElementDirty(deathDisplay);\n\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damage => (\n damage[attrRoundId] == activeRoundId\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n ));\n damageRecords[damageIndex][flagCommanderDeaths] = newDeaths;\n\n PageMtgGame.renderCommanderDamageLog();\n\n // PageMtgGame.debouncedSave();\n this.updateAndToggleShowButtonsSaveCancel();\n }\n\n toggleEliminate(playerId) {\n const card = document.querySelector(`.player-card[data-player-id=\"${playerId}\"]`);\n if (!card) return;\n\n const eliminateBtn = card.querySelector(`.eliminate-btn[data-player-id=\"${playerId}\"]`);\n const wasEliminated = card.classList.contains('eliminated');\n\n if (wasEliminated) {\n card.classList.remove('eliminated');\n eliminateBtn.textContent = 'Eliminate';\n } else {\n card.classList.add('eliminated');\n eliminateBtn.textContent = 'Revive';\n }\n const isEliminated = card.classList.contains('eliminated');\n\n const activeRoundId = PageMtgGame.getActiveRoundId();\n const damageIndex = damageRecords.findIndex(damage => (\n damage[attrRoundId] == activeRoundId\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] == null\n ));\n damageRecords[damageIndex][flagIsEliminated] = isEliminated;\n\n DOM.setElementAttributeValueCurrent(eliminateBtn, isEliminated);\n DOM.isElementDirty(eliminateBtn);\n\n this.reorderPlayerCards();\n PageMtgGame.renderCommanderDamageLog();\n\n // PageMtgGame.debouncedSave();\n this.updateAndToggleShowButtonsSaveCancel();\n }\n reorderPlayerCards() {\n let playerGrid = document.getElementById('playersGrid');\n let currentPlayerCards = playerGrid.querySelectorAll('.player-card');\n let newPlayerCards = [];\n let playerCardMetas = [];\n currentPlayerCards.forEach((playerCard, index) => {\n newPlayerCards.push(playerCard.cloneNode(true));\n playerCardMetas.push({\n [flagIsEliminated]: playerCard.classList.contains(flagIsEliminated)\n , [attrPlayerId]: playerCard.dataset[\"playerId\"]\n , [flagDisplayOrder]: index\n });\n });\n let activeRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n let newPlayerGridInnerHTML = '';\n let playerIdA, playerIdB, isEliminatedAsIntA, isEliminatedAsIntB, playerA, playerB, indexPlayerCard;\n playerCardMetas.sort((a, b) => {\n playerIdA = a[attrPlayerId];\n playerIdB = b[attrPlayerId];\n isEliminatedAsIntA = PageMtgGame.isPlayerEliminated(playerIdA, activeRoundDisplayOrder) ? 1 : 0;\n isEliminatedAsIntB = PageMtgGame.isPlayerEliminated(playerIdB, activeRoundDisplayOrder) ? 1 : 0;\n playerA = players.filter(p => p[attrPlayerId] == playerIdA)[0];\n playerB = players.filter(p => p[attrPlayerId] == playerIdB)[0];\n return (\n players.length * isEliminatedAsIntA\n + playerA[flagDisplayOrder]\n ) - (\n players.length * isEliminatedAsIntB\n + playerB[flagDisplayOrder]\n );\n }).forEach((playerCardMeta) => {\n indexPlayerCard = playerCardMeta[flagDisplayOrder];\n newPlayerGridInnerHTML += newPlayerCards[indexPlayerCard].outerHTML;\n });\n\n playerGrid.innerHTML = newPlayerGridInnerHTML;\n\n playerGrid.querySelectorAll('.' + flagInitialised).forEach((initialisedElement) => {\n initialisedElement.classList.remove(flagInitialised);\n });\n\n this.hookupPlayerCardEvents();\n }\n static isPlayerEliminated(playerId, roundDisplayOrder = null) {\n if (roundDisplayOrder == null) roundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();\n const filteredRoundIds = rounds.filter(round => round[flagDisplayOrder] <= roundDisplayOrder)\n .map(round => round[attrRoundId]);\n let hasDamageWithIsEliminated = damageRecords.filter(damage => (\n // damage[attrRoundId] <= roundDisplayOrder\n filteredRoundIds.includes(damage[attrRoundId])\n && damage[attrPlayerId] == playerId\n && damage[flagIsEliminated]\n )).length > 0;\n let damageFromOtherPlayers = {};\n let otherPlayerId;\n damageRecords.filter(damage => (\n // damage[attrRoundId] <= roundId\n filteredRoundIds.includes(damage[attrRoundId])\n && damage[attrPlayerId] == playerId\n && damage[attrReceivedFromCommanderPlayerId] != null\n ))\n .forEach((damage) => {\n otherPlayerId = damage[attrReceivedFromCommanderPlayerId];\n damageFromOtherPlayers[otherPlayerId] = \n damage[flagLifeLoss]\n + ((damageFromOtherPlayers[otherPlayerId] == null) ? 0 : damageFromOtherPlayers[otherPlayerId]);\n });\n let maxDamageFromOtherCommander = Object.keys(damageFromOtherPlayers)\n .map((playerId) => damageFromOtherPlayers[playerId])\n .reduce((acc, cur) => Math.max(acc, cur), 0);\n let totalDamageTaken = damageRecords.filter(damage => (\n // damage[attrRoundId] <= roundId\n filteredRoundIds.includes(damage[attrRoundId])\n && damage[attrPlayerId] == playerId\n ))\n .map((damage) => damage[flagLifeLoss] - damage[flagLifeGain])\n .reduce((a, b) => a + b, 0);\n console.log({ roundDisplayOrder, filteredRoundIds, hasDamageWithIsEliminated, maxDamageFromOtherCommander, totalDamageTaken });\n return (\n hasDamageWithIsEliminated\n || maxDamageFromOtherCommander >= 21\n || totalDamageTaken >= game[flagStartingLife]\n );\n }\n\n static updatePlayerSetup() {\n const playerCountInput = document.getElementById('playerCount');\n if (!playerCountInput) return;\n\n const playerCount = parseInt(playerCountInput.value);\n const grid = document.getElementById('playerSetupGrid');\n if (!grid) return;\n\n grid.innerHTML = '';\n const wrapperTemplate = document.getElementById(playerSetupWrapperTemplateId);\n let player, wrapper, wrapperHeading, userDdl, deckDdl, nameInput;\n for (let i = 0; i < playerCount; i++) {\n if (i < players.length) {\n player = players[i];\n }\n else {\n player = PageMtgGame.makeDefaultGamePlayer();\n players.push(player);\n }\n wrapper = wrapperTemplate.cloneNode(true);\n wrapper.removeAttribute(\"id\");\n wrapper.setAttribute(flagDisplayOrder, i + 1);\n wrapper.classList.remove(flagIsCollapsed);\n wrapperHeading = wrapper.querySelector('label');\n wrapperHeading.innerText = 'Player ' + (i + 1);\n userDdl = wrapper.querySelector('.playerUser select');\n DOM.setElementValuesCurrentAndPrevious(userDdl, player[attrUserId]);\n deckDdl = wrapper.querySelector('.playerDeck select');\n DOM.setElementValuesCurrentAndPrevious(deckDdl, player[attrDeckId]);\n nameInput = wrapper.querySelector('.playerName input');\n DOM.setElementValuesCurrentAndPrevious(nameInput, player[flagName]);\n console.log('player: ', player);\n grid.appendChild(wrapper);\n }\n }\n static makeDefaultGamePlayer() {\n return {\n [attrPlayerId]: -players.length\n , [attrGameId]: gameId\n , [attrUserId]: user[attrUserId]\n , [attrDeckId]: 0\n , [flagName]: \"\"\n , [flagNotes]: null\n , [flagDisplayOrder]: players.length\n , [flagActive]: true\n };\n }\n\n async startGame() {\n const playerCountInput = document.getElementById('playerCount');\n if (!playerCountInput) return;\n\n const playerCount = parseInt(playerCountInput.value);\n const playersToSave = [];\n\n let playerSetupWrapper, playerId, player, userDdl, userId, deckDdl, deckId, nameInput, name;\n for (let i = 0; i < playerCount; i++) {\n playerSetupWrapper = document.querySelector('.player-name-input-wrapper[' + flagDisplayOrder + '=\"' + (i + 1) + '\"]');\n userDdl = playerSetupWrapper.querySelector('.playerUser select');\n deckDdl = playerSetupWrapper.querySelector('.playerDeck select');\n nameInput = playerSetupWrapper.querySelector('.playerName input');\n \n userId = DOM.getElementValueCurrent(userDdl);\n deckId = DOM.getElementValueCurrent(deckDdl);\n name = nameInput ? nameInput.value.trim() || null : null; // `Player ${i + 1}` : `Player ${i + 1}`;\n\n playerId = playerSetupWrapper.getAttribute(attrPlayerId);\n player = players.filter(p => p[attrPlayerId] == playerId)[0];\n playersToSave.push({\n ...player\n , [attrGameId]: gameId\n , [attrUserId]: userId\n , [attrDeckId]: deckId\n , [flagName]: name\n , [flagDisplayOrder]: i + 1\n , [flagActive]: true\n });\n }\n\n // Save players to server\n const comment = 'Save players';\n const self = this;\n API.saveGamePlayers(playersToSave, null, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n self.leave();\n window.location.reload();\n }\n else {\n console.error('Failed to save players:', data[flagMessage]);\n PageMtgGame.showError('An error occurred while creating the game');\n }\n })\n .catch(error => {\n console.error('Error creating game:', error);\n PageMtgGame.showError('An error occurred while creating the game');\n })\n .finally(() => {\n });\n }\n\n static resetGame() {\n if (confirm('Are you sure you want to start a new game? Current game will be lost.')) {\n localStorage.removeItem(`mtgGame_${gameId}`);\n window.location.href = hashPageGames;\n }\n }\n\n async saveGame() {\n /*\n const gameState = {\n [flagPlayer]: players\n , [flagRound]: rounds\n , [flagDamage]: damageRecords\n };\n if (gameState[flagPlayer].length > 0) {\n localStorage.setItem(`mtgGame_${gameId}`, JSON.stringify(gameState));\n PageMtgGame.showSaveIndicator();\n }\n */\n const comment = 'Save player damage';\n const self = this;\n API.saveGameRoundPlayerDamages(rounds, damageRecords, null, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n self.leave();\n window.location.reload();\n }\n else {\n console.error('Failed to save player damages:', data[flagMessage]);\n PageMtgGame.showError('An error occurred while saving player damages');\n }\n })\n .catch(error => {\n console.error('Error saving player damages:', error);\n PageMtgGame.showError('An error occurred while saving player damages');\n })\n .finally(() => {\n });\n }\n /*\n static debouncedSave() {\n clearTimeout(PageMtgGame._saveTimeout);\n PageMtgGame._saveTimeout = setTimeout(() => PageMtgGame.saveGame(), 500);\n }\n\n static showSaveIndicator() {\n const indicator = document.getElementById('saveIndicator');\n if (indicator) {\n indicator.classList.add('show');\n setTimeout(() => {\n indicator.classList.remove('show');\n }, 2000);\n }\n }\n */\n saveRecordsTableDirty() {\n this.saveGame();\n }\n static showError(message) {\n // Check if there's an overlay error element\n const errorOverlay = document.getElementById('overlayError');\n if (errorOverlay) {\n const errorLabel = errorOverlay.querySelector('.error-message, #labelError');\n if (errorLabel) {\n errorLabel.textContent = message;\n }\n errorOverlay.classList.remove('hidden');\n errorOverlay.style.display = 'flex';\n } else {\n // Fallback to alert\n alert(message);\n }\n }\n\n updateAndToggleShowButtonsSaveCancel() {\n // let pageBody = document.querySelector(idPageBody);\n let isDirty = DOM.hasDirtyChildrenContainer(pageBody);\n\n let buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;\n let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);\n let areVisibleSaveCancelButtons = !buttonSave.classList.contains(flagIsCollapsed);\n \n console.log({ pageBody, isDirty, areVisibleSaveCancelButtons });\n\n this.toggleShowButtonsSaveCancel(isDirty || areVisibleSaveCancelButtons);\n }\n\n leave() {\n super.leave();\n }\n}\n\n// Static timeout reference for debouncing\nPageMtgGame._saveTimeout = null;\n","\nimport API from \"../../api.js\";\nimport TableBasePage from \"../base_table.js\";\nimport Utils from \"../../lib/utils.js\";\n\nexport default class PageMtgGames extends TableBasePage {\n static hash = hashPageMtgGames;\n static attrIdRowObject = attrGameId;\n callSaveTableContent = API.saveGame;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n hookupFilters() {\n /*\n this.sharedHookupFilters();\n this.hookupFilterActive();\n */\n }\n\n loadRowTable(rowJson) {\n if (rowJson == null) return;\n if (_verbose) { Utils.consoleLogIfNotProductionEnvironment(\"applying data row: \", rowJson); }\n }\n getJsonRow(row) {\n return;\n }\n initialiseRowNew(tbody, row) {\n }\n postInitialiseRowNewCallback(tbody) {\n }\n\n hookupTableMain() {\n super.hookupTableMain();\n // this.hookupTableMainRows();\n this.hookupTcgGames();\n // PageMtgGames.hideNewGameForm();\n }\n hookupTcgGames() {\n console.log(\"hookupTableMain PageMtgGames\");\n // Initialize form submission\n const newGameForm = document.getElementById('newGameForm');\n if (newGameForm) {\n newGameForm.addEventListener('submit', this.handleNewGameSubmit.bind(this)); // () => { this.handleNewGameSubmit.bind(this); });\n }\n\n // Initialize filter form\n const filterForm = document.getElementById('formFilters');\n if (filterForm) {\n filterForm.addEventListener('submit', PageMtgGames.handleFilterSubmit);\n }\n\n // Close modal on escape key\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape') {\n PageMtgGames.hideNewGameForm();\n }\n });\n\n // Close modal on backdrop click\n const modal = document.getElementById('newGameModal');\n if (modal) {\n modal.addEventListener('click', function(e) {\n if (e.target === modal) {\n PageMtgGames.hideNewGameForm();\n }\n });\n }\n\n // Button onclicks\n const newGameButton = document.getElementById('btnNewGame');\n if (newGameButton) {\n newGameButton.addEventListener('click', PageMtgGames.showNewGameForm);\n }\n const cancelNewGameButtons = document.querySelectorAll(\n '#newGameForm .form-actions .btn-tcg.btn-tcg-secondary'\n + ','\n + '#newGameModal .modal-content .modal-header .modal-close'\n );\n if (cancelNewGameButtons.length > 0) {\n cancelNewGameButtons.forEach((button) => {\n button.addEventListener('click', PageMtgGames.hideNewGameForm);\n });\n }\n\n }\n static showNewGameForm() {\n const modal = document.getElementById('newGameModal');\n if (modal) {\n modal.classList.remove(flagIsCollapsed);\n document.body.style.overflow = 'hidden';\n\n // Focus on first input\n const firstInput = modal.querySelector('input, select');\n if (firstInput) {\n firstInput.focus();\n }\n }\n }\n static hideNewGameForm() {\n const modal = document.getElementById('newGameModal');\n if (modal) {\n modal.classList.add(flagIsCollapsed);\n document.body.style.overflow = '';\n\n // Reset form\n const form = document.getElementById('newGameForm');\n if (form) {\n form.reset();\n }\n }\n }\n async handleNewGameSubmit(e) {\n e.preventDefault();\n\n const form = e.target;\n const formData = new FormData(form);\n\n const gameType = formData.get('game_type');\n const gameData = {\n [attrGameId]: -1\n , [flagIsCommander]: gameType === 'commander'\n , [flagIsDraft]: gameType === 'draft'\n , [flagIsSealed]: gameType === 'sealed'\n , [flagLocationName]: formData.get(flagLocationName) || null\n , [flagNotes]: formData.get(flagNotes) || null\n , [flagStartOn]: new Date().toISOString()\n , [flagStartingLife]: formData.get(flagStartingLife) || 40\n , [flagActive]: true\n };\n\n const submitBtn = form.querySelector('button[type=\"submit\"]');\n const originalText = submitBtn.textContent;\n submitBtn.textContent = 'Creating...';\n submitBtn.disabled = true;\n\n const games = [gameData];\n const comment = 'Create new game';\n API.saveGame(games, form, comment)\n .then(data => {\n if (data[flagStatus] == flagSuccess) {\n if (_verbose) { \n Utils.consoleLogIfNotProductionEnvironment('Records saved!');\n Utils.consoleLogIfNotProductionEnvironment('Data received:', data);\n }\n const gamePageHash = `${hashPageGame}/${data[attrGameId]}`;\n let filtersJson = {};\n this.leave();\n API.goToHash(gamePageHash, filtersJson);\n }\n else {\n Utils.consoleLogIfNotProductionEnvironment(\"error: \" + data[flagMessage]);\n // OverlayError.show(data[flagMessage]);\n window.location.reload();\n }\n })\n .catch(error => {\n console.error('Error creating game:', error);\n PageMtgGames.showError('An error occurred while creating the game');\n })\n .finally(() => {\n submitBtn.textContent = originalText;\n submitBtn.disabled = false;\n });\n \n }\n static handleFilterSubmit(e) {\n // Let the form submit normally - it will reload with query params\n // You can add client-side filtering here if needed\n }\n static getCSRFToken() {\n // Try meta tag first\n const metaTag = document.querySelector('meta[name=\"csrf-token\"]');\n if (metaTag) {\n return metaTag.getAttribute('content');\n }\n\n // Try hidden input\n const hiddenInput = document.querySelector('input[name=\"csrf_token\"]');\n if (hiddenInput) {\n return hiddenInput.value;\n }\n\n // Try cookie\n const cookies = document.cookie.split(';');\n for (let cookie of cookies) {\n const [name, value] = cookie.trim().split('=');\n if (name === 'csrf_token') {\n return value;\n }\n }\n\n return '';\n }\n static showError(message) {\n // Check if there's an overlay error element\n const errorOverlay = document.getElementById('overlayError');\n if (errorOverlay) {\n const errorLabel = errorOverlay.querySelector('.error-message, #labelError');\n if (errorLabel) {\n errorLabel.textContent = message;\n }\n errorOverlay.classList.remove(flagIsCollapsed);\n errorOverlay.style.display = 'flex';\n } else {\n // Fallback to alert\n alert(message);\n }\n }\n static showSuccess(message) {\n // Could implement a toast notification here\n console.log('Success:', message);\n }\n static joinGame(gameId) {\n window.location.href = `${hashPageGame}/${gameId}`;\n }\n static async deleteGame(gameId) {\n if (!confirm('Are you sure you want to delete this game? This action cannot be undone.')) {\n return;\n }\n\n try {\n const gameData = {\n 'game_id': gameId,\n 'active': false\n };\n\n const response = await fetch(hashSaveGame, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-CSRFToken': PageMtgGames.getCSRFToken()\n },\n body: JSON.stringify({\n [flagGame]: [gameData],\n 'form-filters': {},\n 'comment': 'Game deleted'\n })\n });\n\n const result = await response.json();\n\n if (result.status === 'success') {\n // Remove the row from the table\n const row = document.querySelector(`tr[data-game-id=\"${gameId}\"]`);\n if (row) {\n row.style.animation = 'tcg-fadeOut 0.3s ease-out forwards';\n setTimeout(() => row.remove(), 300);\n }\n } else {\n PageMtgGames.showError(result.message || 'Failed to delete game');\n }\n } catch (error) {\n console.error('Error deleting game:', error);\n PageMtgGames.showError('An error occurred while deleting the game');\n }\n }\n\n toggleShowButtonsSaveCancel() {}\n leave() {\n super.leave();\n }\n}\n","\n\nimport API from \"../../api.js\";\nimport BasePage from \"../base.js\";\nimport DOM from \"../../dom.js\";\nimport Events from \"../../lib/events.js\";\n\nexport default class PageMtgHome extends BasePage {\n static hash = hashPageMtgHome;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n this.hookupTcgHome();\n }\n\n hookupTcgHome() {\n }\n\n leave() {\n super.leave();\n }\n}\n","import BasePage from \"../base.js\";\n\nexport default class PageAccessibilityReport extends BasePage {\n static hash = hashPageAccessibilityReport;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}\n","import BasePage from \"../base.js\";\n\nexport default class PageAccessibilityStatement extends BasePage {\n static hash = hashPageAccessibilityStatement;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}\n","\nimport BasePage from \"../base.js\";\n\nexport default class PageLicense extends BasePage {\n static hash = hashPageLicense;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}","\nimport BasePage from \"../base.js\";\n\nexport default class PagePrivacyPolicy extends BasePage {\n static hash = hashPagePrivacyPolicy;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}","import BasePage from \"../base.js\";\n\nexport default class PageRetentionSchedule extends BasePage {\n static hash = hashPageDataRetentionSchedule;\n\n constructor(router) {\n super(router);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n leave() {\n super.leave();\n }\n}\n","\n\nexport default class MixinPage {\n constructor(pageCurrent) {\n this.page = pageCurrent;\n }\n\n initialize() {\n Utils.consoleLogIfNotProductionEnvironment('hookup start for ', this.page.hash);\n this.hookupFilters();\n this.hookupLocalStorage();\n }\n hookupFilters() {\n }\n hookupLocalStorage() {\n \n }\n \n leave() {}\n}\n","\nimport MixinPage from \"./mixin.js\";\n\nexport default class TableMixinPage extends MixinPage {\n constructor(pageCurrent) {\n super(pageCurrent);\n }\n initialize() {\n super.initialize();\n this.hookupFilters();\n this.hookupTable();\n }\n hookupFilters() {\n // Implement filter-specific functionality here\n }\n hookupTable() {\n // Implement table-specific functionality here\n }\n}","\nimport API from \"../../api.js\";\nimport TableMixinPage from \"../mixin_table.js\";\nimport DOM from \"../../dom.js\";\nimport TableBasePage from \"../base_table.js\";\n\nexport default class PageUser extends TableBasePage {\n static hash = hashPageUserAccount;\n static attrIdRowObject = attrUserId;\n callSaveTableContent = API.saveUsers;\n\n constructor(router) {\n super(router);\n this.mixin = new TableMixinPage(this);\n }\n\n initialize() {\n this.sharedInitialize();\n this.hookupTableMain();\n }\n\n\n hookupFilters() {\n }\n\n loadRowTable(rowJson) {\n if (rowJson == null) return;\n if (_verbose) { Utils.consoleLogIfNotProductionEnvironment(\"applying data row: \", rowJson); }\n }\n getTableRecords(dirtyOnly = false) {\n dirtyOnly = true;\n let container = document.querySelector('.' + flagCard + '.' + flagUser);\n return [this.getJsonRow(container)];\n }\n getJsonRow(container) {\n console.log(\"getJsonRow: \", container);\n if (container == null) return;\n let inputFirstname = container.querySelector(' #' + flagFirstname);\n let inputSurname = container.querySelector(' #' + flagSurname);\n let inputEmail = container.querySelector(' #' + flagEmail);\n\n let idUser = container.getAttribute(attrUserId);\n \n let jsonRow = {\n [attrUserAuth0Id]: null\n , [flagEmail]: null\n , [flagIsEmailVerified]: null\n , [flagIsSuperUser]: null\n , [flagCanAdminUser]: null\n };\n\n jsonRow[attrUserId] = idUser;\n jsonRow[flagFirstname] = DOM.getElementAttributeValueCurrent(inputFirstname);\n jsonRow[flagSurname] = DOM.getElementAttributeValueCurrent(inputSurname);\n jsonRow[flagEmail] = DOM.getElementAttributeValueCurrent(inputEmail);\n return jsonRow;\n }\n \n initialiseRowNew(tbody, row) {\n }\n postInitialiseRowNewCallback(tbody) {\n }\n\n hookupTableMain() {\n super.hookupTableMain();\n this.hookupFieldsFirstname();\n this.hookupFieldsSurname();\n this.hookupFieldsEmail();\n }\n hookupFieldsFirstname() {\n this.hookupChangeHandlerTableCells('.' + flagCard + '.' + flagUser + ' #' + flagFirstname);\n }\n hookupFieldsSurname() {\n this.hookupChangeHandlerTableCells('.' + flagCard + '.' + flagUser + ' #' + flagSurname);\n }\n hookupFieldsEmail() {\n this.hookupChangeHandlerTableCells('.' + flagCard + '.' + flagUser + ' #' + flagEmail);\n }\n\n leave() {\n super.leave();\n }\n}\n","\nimport API from \"../../api\";\nimport TableMixinPage from \"../mixin_table\";\nimport DOM from \"../../dom\";\nimport TableBasePage from \"../base_table\";\nimport Utils from \"../../lib/utils\";\n\nexport default class PageUsers extends TableBasePage {\n static hash = hashPageUserAccounts;\n static attrIdRowObject = attrUserId;\n callSaveTableContent = API.saveUsers;\n\n constructor(router) {\n super(router);\n this.mixin = new TableMixinPage(this);\n }\n\n initialize() {\n this.sharedInitialize();\n }\n\n hookupFilters() {\n this.sharedHookupFilters();\n this.hookupFilterActive();\n }\n\n loadRowTable(rowJson) {\n if (rowJson == null) return;\n if (_verbose) { Utils.consoleLogIfNotProductionEnvironment(\"applying data row: \", rowJson); }\n }\n getJsonRow(row) {\n if (row == null) return;\n let inputFirstname = row.querySelector('td.' + flagFirstname + ' .' + flagFirstname);\n let inputSurname = row.querySelector('td.' + flagSurname + ' .' + flagSurname);\n let inputNotes = row.querySelector('td.' + flagNotes + ' .' + flagNotes);\n let buttonActive = row.querySelector('td.' + flagActive + ' .' + flagActive);\n\n let jsonRow = {\n [attrUserAuth0Id]: null\n , [flagEmail]: null\n , [flagIsEmailVerified]: null\n , [flagIsSuperUser]: null\n , [flagCanAdminUser]: null\n };\n jsonRow[attrUserId] = row.getAttribute(attrUserId);\n jsonRow[flagFirstname] = DOM.getElementAttributeValueCurrent(inputFirstname);\n jsonRow[flagSurname] = DOM.getElementAttributeValueCurrent(inputSurname);\n jsonRow[flagNotes] = DOM.getElementAttributeValueCurrent(inputNotes);\n jsonRow[flagActive] = buttonActive.classList.contains(flagDelete);\n\n console.log(\"jsonRow\");\n console.log(jsonRow);\n\n return jsonRow;\n }\n \n initialiseRowNew(tbody, row) {\n \n }\n postInitialiseRowNewCallback(tbody) {\n let newRows = tbody.querySelectorAll('tr.' + flagRowNew);\n let newestRow = newRows[0];\n let clickableElementsSelector = [].join('');\n newestRow.querySelectorAll(clickableElementsSelector).forEach((clickableElement) => {\n clickableElement.click();\n });\n }\n\n hookupTableMain() {\n super.hookupTableMain();\n this.hookupFieldsFirstname();\n this.hookupFieldsSurname();\n this.hookupFieldsNotesTable();\n this.hookupFieldsActive();\n }\n hookupFieldsFirstname() {\n this.hookupChangeHandlerTableCells(flagFirstname);\n }\n hookupFieldsSurname() {\n this.hookupChangeHandlerTableCells(flagSurname);\n }\n\n leave() {\n super.leave();\n }\n}\n","\n// Pages\n// Core\n// TCG\nimport PageMtgDecks from './pages/tcg/mtg_decks.js';\nimport PageMtgGame from './pages/tcg/mtg_game.js';\nimport PageMtgGames from './pages/tcg/mtg_games.js';\nimport PageMtgHome from './pages/tcg/mtg_home.js';\n// Legal\nimport PageAccessibilityReport from './pages/legal/accessibility_report.js';\nimport PageAccessibilityStatement from './pages/legal/accessibility_statement.js';\nimport PageLicense from './pages/legal/license.js';\nimport PagePrivacyPolicy from './pages/legal/privacy_policy.js';\nimport PageRetentionSchedule from './pages/legal/retention_schedule.js';\n// User\n// import PageUserLogin from './pages/user/login.js';\n// import PageUserLogout from './pages/user/logout.js';\nimport PageUser from './pages/user/user.js';\nimport PageUsers from './pages/user/users.js';\n\nimport API from './api.js';\nimport DOM from './dom.js';\nimport Utils from './lib/utils.js';\n\n\nexport default class Router {\n constructor() {\n // Pages\n this.pages = {};\n // Core\n // TCG\n this.pages[hashPageMtgDecks] = { name: 'PageMtgDecks', module: PageMtgDecks };\n this.pages[hashPageMtgGame] = { name: 'PageMtgGame', module: PageMtgGame };\n this.pages[hashPageMtgGames] = { name: 'PageMtgGames', module: PageMtgGames };\n this.pages[hashPageMtgHome] = { name: 'PageMtgGame', module: PageMtgHome };\n // Legal\n this.pages[hashPageAccessibilityStatement] = { name: 'PageAccessibilityStatement', module: PageAccessibilityStatement };\n this.pages[hashPageDataRetentionSchedule] = { name: 'PageDataRetentionSchedule', module: PageRetentionSchedule };\n this.pages[hashPageLicense] = { name: 'PageLicense', module: PageLicense };\n this.pages[hashPagePrivacyPolicy] = { name: 'PagePrivacyPolicy', module: PagePrivacyPolicy };\n // User\n // this.pages[hashPageUserLogin] = { name: 'PageUserLogin', module: PageUserLogin }; // pathModule: './pages/user/login.js' };\n // this.pages[hashPageUserLogout] = { name: 'PageUserLogout', module: PageUserLogout }; // pathModule: './pages/user/logout.js' };\n this.pages[hashPageUserAccount] = { name: 'PageUser', module: PageUser };\n this.pages[hashPageUserAccounts] = { name: 'PageUsers', module: PageUsers };\n // Routes\n this.routes = {};\n // Core\n // TCG\n this.routes[hashPageMtgDecks] = (isPopState = false) => this.navigateToHash(hashPageMtgDecks, isPopState);\n this.routes[hashPageMtgGame] = (isPopState = false) => this.navigateToHash(hashPageMtgGame, isPopState);\n this.routes[hashPageMtgGames] = (isPopState = false) => this.navigateToHash(hashPageMtgGames, isPopState);\n this.routes[hashPageMtgHome] = (isPopState = false) => this.navigateToHash(hashPageMtgHome, isPopState);\n // Legal\n this.routes[hashPageAccessibilityStatement] = (isPopState = false) => this.navigateToHash(hashPageAccessibilityStatement, isPopState);\n this.routes[hashPageDataRetentionSchedule] = (isPopState = false) => this.navigateToHash(hashPageDataRetentionSchedule, isPopState);\n this.routes[hashPageLicense] = (isPopState = false) => this.navigateToHash(hashPageLicense, isPopState);\n this.routes[hashPagePrivacyPolicy] = (isPopState = false) => this.navigateToHash(hashPagePrivacyPolicy, isPopState);\n // User\n // this.routes[hashPageUserLogin] = (isPopState = false) => this.navigateToHash(hashPageUserLogin, isPopState);\n // this.routes[hashPageUserLogout] = (isPopState = false) => this.navigateToHash(hashPageUserLogout, isPopState);\n this.routes[hashPageUserAccount] = (isPopState = false) => this.navigateToHash(hashPageUserAccount, isPopState);\n this.routes[hashPageUserAccounts] = (isPopState = false) => this.navigateToHash(hashPageUserAccounts, isPopState);\n this.initialize();\n }\n loadPage(hashPage, isPopState = false) {\n const PageClass = this.getClassPageFromHash(hashPage);\n this.currentPage = new PageClass(this);\n this.currentPage.initialize(isPopState);\n window.addEventListener('beforeunload', () => this.currentPage.leave());\n }\n getClassPageFromHash(hashPage) {\n \n let pageJson = this.pages[hashPage];\n try {\n const module = pageJson.module;\n return module; \n }\n catch (error) {\n Utils.consoleLogIfNotProductionEnvironment(\"this.pages: \", this.pages);\n console.error('Page not found:', hashPage);\n throw error;\n }\n }\n initialize() {\n window.addEventListener('popstate', this.handlePopState.bind(this));\n }\n handlePopState(event) {\n this.loadPageCurrent();\n }\n loadPageCurrent() {\n const hashPageCurrent = DOM.getHashPageCurrent();\n this.loadPage(hashPageCurrent);\n }\n navigateToHash(hash, data = null, params = null, isPopState = false) {\n let url = API.getUrlFromHash(hash, params);\n history.pushState({data: data, params: params}, '', hash);\n API.goToUrl(url, data);\n }\n \n navigateToUrl(url, data = null, appendHistory = true) {\n // this.beforeLeave();\n if (appendHistory) history.pushState(data, '', url);\n url = API.parameteriseUrl(url, data);\n API.goToUrl(url);\n }\n\n static loadPageBodyFromResponse(response) {\n DOM.loadPageBody(response.data);\n }\n}\n\nexport const router = new Router();\n","\n'use strict';\n\nimport DOM from './dom.js';\nimport Router from './router.js';\n\n\nclass App {\n constructor() {\n this.dom = new DOM();\n this.router = new Router();\n }\n\n initialize() {\n this.setupEventListeners();\n this.start();\n }\n\n setupEventListeners() {\n // document.addEventListener('click', this.handleGlobalClick.bind(this));\n }\n\n handleGlobalClick(event) {\n }\n\n start() {\n this.initPageCurrent();\n }\n\n initPageCurrent() {\n this.router.loadPageCurrent();\n }\n \n}\n\nconst app = new App();\n\nfunction domReady(fn) {\n if (document.readyState !== 'loading') {\n fn();\n } else {\n document.addEventListener('DOMContentLoaded', fn);\n }\n}\n\ndomReady(() => {\n app.initialize();\n});\n\nwindow.app = app;\n\nexport default app;","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};"],"names":["Validation","isEmpty","object","undefined","length","isString","trim","i","isValidNumber","value","positiveOnly","isNaN","parseFloat","getDataContentType","params","data","contentType","JSON","stringify","Data","ContentType","arrayContainsItem","array","itemValue","hasItem","isJQueryElementArray","jQuery","document","querySelectorAll","is","isDate","Date","getTime","dictHasKey","d","k","areEqualDicts","dict1","dict2","keys1","Object","keys","keys2","key","imageExists","url","callback","img","Image","onload","onerror","src","toFixedOrDefault","decimalPlaces","defaultValue","toFixed","Utils","DOM","setElementAttributesValuesCurrentAndPrevious","element","setElementAttributeValueCurrent","setElementAttributeValuePrevious","setAttribute","attrValueCurrent","attrValuePrevious","setElementValuesCurrentAndPrevious","setElementValueCurrent","tagName","toUpperCase","type","checked","textContent","setElementValueCurrentIfEmpty","getElementValueCurrent","getCellFromElement","closest","getRowFromElement","flagRow","selector","getClosestParent","parentSelector","parent","parentElement","matches","convertForm2JSON","elementForm","dataForm","containersFilter","flagContainerInput","flagFilter","containerFilter","labelFilter","keyFilter","filter","indexFilter","querySelector","getAttribute","loadPageBody","contentNew","pageBody","idPageBody","innerHTML","getHashPageCurrent","hashPageCurrent","body","dataset","page","updateAndCheckIsElementDirty","isElementDirty","isDirty","handleDirtyElement","toggleElementHasClassnameFlag","flagDirty","elementHasFlag","flag","elementAlreadyHasFlag","classList","contains","add","remove","hasDirtyChildrenContainer","container","hasDirtyChildrenNotDeletedContainer","flagDelete","returnVal","flagButton","flagActive","getElementAttributeValueCurrent","flagCheckbox","flagIsChecked","getElementAttributeValuePrevious","scrollToElement","scrollTop","offset","top","isElementInContainer","containerBounds","getBoundingClientRect","elementBounds","left","height","width","alertError","errorType","errorText","alert","createOptionUnselectedProductVariation","flagProductVariationType","flagNameAttrOptionText","flagName","flagNameAttrOptionValue","attrIdProductVariationType","flagProductVariation","attrIdProductVariation","createOption","optionJson","text","option","createElement","selected","escapeHtml","div","unescapeHtml","html","innerText","API","getCsrfToken","idCSRFToken","request","hashEndpoint","method","getUrlFromHash","csrfToken","options","headers","flagCsrfToken","response","fetch","ok","Error","status","json","error","console","hash","hashPageHome","parameteriseUrl","_pathHost","URLSearchParams","toString","goToUrl","window","location","href","goToHash","loginUser","flagCallback","hashPageUserLogin","saveUsers","users","formFilters","comment","dataRequest","flagFormFilters","flagUser","flagComment","hashSaveUserUser","getIsGameDataOutdated","game","attrGameId","flagGame","saveGame","hashSaveGame","getGamePlayers","gameId","saveGamePlayers","players","flagPlayer","hashSaveGamePlayer","getGameRounds","getGameDamageRecords","saveGameRoundPlayerDamages","rounds","damages","flagDamage","flagRound","hashSaveGameRoundPlayerDamage","BusinessObjects","getOptionJsonFromObjectJsonAndKeys","objectJson","keyText","keyValue","valueSelected","getOptionJsonFromObjectJson","getObjectText","getListObjectsFromIdDictAndCsv","idDict","idCsv","listObjects","ids","split","id","push","Events","initialiseEventHandler","selectorElement","classInitialised","eventHandler","forEach","hookupEventHandler","eventType","flagInitialised","addEventListener","event","stopPropagation","LocalStorage","getLocalStorage","parse","localStorage","getItem","setLocalStorage","newLS","setItem","getListFromDict","dict","list","consoleLogIfNotProductionEnvironment","message","environment","is_production","log","OverlayConfirm","hookup","callbackSuccess","idOverlayConfirm","flagCancel","buttonCancel","overlay","style","visibility","flagSubmit","buttonConfirm","textarea","show","flagIsCollapsed","OverlayError","BasePage","constructor","router","title","titlePageCurrent","name","initialize","sharedInitialize","logInitialisation","hookupCommonElements","hookupLogos","hookupNavigation","hookupOverlays","flagImageLogo","flagLogo","navigateToHash","idButtonHamburger","overlayHamburger","idOverlayHamburger","flagExpanded","hookupButtonsNavUserAccount","hookupButtonsNavUserLogout","hookupButtonsNavUserLogin","hookupButtonsNav","buttonSelector","button","pageHash","flagNavUserLogin","navigator","preventDefault","leave","then","Success","Message","hookupOverlayFromId","idOverlayError","idOverlay","display","hookupButtonSave","flagContainer","flagSave","target","setLocalStoragePage","dataPage","getLocalStoragePage","toggleShowButtonsSaveCancel","buttonContainerSelector","buttonSave","idButtonSave","idButtonCancel","isDirtyFilter","idTableMain","msgError","labelError","idLabelError","TableBasePage","cursorYInitial","rowInitial","placeholder","dragSrcEl","dragSrcRow","hookupTableCellDdls","bind","isPopState","isSinglePageApp","hookupFilters","hookupButtonsSaveCancel","hookupTableMain","saveRecordsTableDirtySinglePageApp","saveRecordsTableDirty","filters","getFormFilters","filtersDefault","callFilterTableContent","sharedHookupFilters","hookupButtonApplyFilters","hookupSearchTextFilter","hookupFilterActive","filterSelector","idFormFilters","flagActiveOnly","filterActiveOld","removeAttribute","parentDiv","isChecked","filterActiveNew","filterActive","svgElement","wasChecked","handleChangeFilter","filterValuePrevious","hookupFilter","filterFlag","handler","areDirtyFilters","tbody","rows","row","dirtyInputs","dirtyInput","isDirtyLabel","initialisedElements","initialisedElement","updateAndToggleShowButtonsSaveCancel","hookupFilterIsNotEmpty","flagIsNotEmpty","idButtonApplyFilters","flagSearch","hookupFilterCommandCategory","attrIdCommandCategory","filterCommandCategory","idCommandCategory","filterCommands","commandsInCategory","command","sortedCommands","sort","a","b","localeCompare","filterCommand","flagCommand","idCommandPrevious","appendChild","dispatchEvent","Event","hookupFilterCommand","attrIdCommand","hookupFilterLocation","attrIdLocation","filtersJson","callbackLoadTableContent","table","getTableMain","bodyTable","rowsJson","flagRows","every","hasOwnProperty","display_order","loadRowTable","rowJson","getAndLoadFilteredTableContentSinglePageApp","catch","hookupButtonCancel","records","getTableRecords","formElement","idTextareaConfirm","callSaveTableContent","flagStatus","flagSuccess","_verbose","flagMessage","dirtyOnly","record","getJsonRow","handleClickAddRowTable","_rowBlank","attrIdRowObject","cloneNode","countRows","initialiseRowNew","prepend","postInitialiseRowNewCallback","cacheRowBlank","selectorRowNew","flagRowNew","rowBlankTemp","initialiseSliderDisplayOrderRowNew","slidersDisplayOrder","flagDisplayOrder","flagSlider","maxDisplayOrder","slider","Math","max","sliderDisplayOrder","hookupSlidersDisplayOrderTable","selectorDisplayOrder","hookupChangeHandlerTableCells","inputSelector","handleChangeNestedElementCellTable","input","wasDirtyParentRows","getAllIsDirtyRowsInParentTree","wasDirtyElement","isDirtyElement","cascadeChangedIsDirtyNestedElementCellTable","tr","isDirtyRow","wasDirtyRow","shift","hookupChangeHandlerTableCellsWhenNotCollapsed","hookupFieldsCodeTable","flagCode","hookupFieldsNameTable","hookupFieldsDescriptionTable","flagDescription","hookupFieldsNotesTable","flagNotes","hookupFieldsActive","flagTable","handleClickRowNew","selectorButton","selectorButtonDelete","selectorButtonUndelete","hookupButtonsRowDelete","hookupButtonsRowUndelete","changeHandler","handleClickButtonRowDelete","changeEvent","changeElement","valuePrevious","wasDirty","parentNode","removeChild","buttonAddTemplate","idContainerTemplateElements","flagAdd","buttonAdd","replaceWith","handleClickButtonRowUndelete","buttonDeleteTemplate","buttonDelete","hookupTdsAccessLevel","hookupTableCellDdlPreviews","flagAccessLevel","accessLevels","fieldFlag","optionList","cellSelector","ddlHookup","ddlSelector","handleClickTableCellDdlPreview","optionObjectList","idSelected","td","ddl","optionObjectJson","toggleColumnCollapsed","flagColumn","isCollapsed","toggleColumnHasClassnameFlag","toggleColumnHeaderCollapsed","hookupFieldsCommandCategory","idTable","flagCommandCategory","filterCommandCategories","hookupCommandCategoryDdls","handleChangeCommandCategoryDdl","ddlCategory","idCommandCategoryRowOld","getIdCommandCategoryRow","idCommandCategoryRowNew","idCommandCategoryFilter","getIdCommandCategoryFilter","tdCommand","ddlCommand","hookupFieldsCommand","parentTr","tdCommandCategory","idCommandCategoryRow","filterCommandList","handleChangeCommandDdl","idCommandNew","getIdCommandRow","commandNew","divCommandCategory","ddlCommandCategory","elementCommandCategory","commandCategoryFilter","commandFilter","valueCurrentCommandCategoryFilter","valueCurrentCommandFilter","parseInt","getHasCommandCategoryFilter","elementCommand","getIdCommandFilter","idCommand","getHasCommandFilter","idCommandFilter","columnFlag","isRequiredFlag","classnameFlag","columnTh","columnThHasFlag","toggleColumnHeaderHasClassnameFlag","areVisibleSaveCancelButtons","PageMtgDecks","hashPageMtgDecks","attrDeckId","saveDeck","newRows","newestRow","clickableElementsSelector","attrCommanderBracketId","join","clickableElement","click","hookupTableMainRows","hookupTableMainIsCommanderCheckboxes","hookupTableMainCommanderBracketPreviews","rowSelector","flagTableMain","isRowExpanded","showSection","toggleShowDeckStatisticsSection","deckId","statisticsSectionTableBody","flagStatistics","deck","decks","newStatisticRowsHtml","statistic","attrStatisticId","flagValue","flagIsCommander","commanderBrackets","PageMtgGame","hashPageMtgGame","hookupTcgGame","reload","initGamePage","pageHeading","updatePlayerSetup","loadGameFromServer","hookupResetButton","hookupPlayerCountInput","hookupStartGameButton","hookupOverlayGameOutdated","hookupGameUpdateCheck","resetGameButton","resetGame","playerCountInput","getElementById","startGameButton","startGame","intervalId","setInterval","isGameDataOutdated","checkLastGameUpdate","clearInterval","isGameDataOutdatedResponse","flagData","pageTitleElement","showOverlayGameOutdated","idOverlayGameOutdated","playersResponse","roundsResponse","damageResponse","Promise","all","setupSection","gameSection","savedPlayers","savedRounds","savedDamageRecords","damageRecords","latestRoundId","getLatestRoundId","latestRound","round","attrRoundId","roundDisplayOrderLabel","getRoundDisplayOrderLabel","renderPlayers","grid","currentRoundDisplayOrder","activeRound","makeDefaultGameRound","previousRoundIds","map","player","index","playerId","attrPlayerId","displayName","makePlayerDisplayName","damagePlayerPairs","maxCommanderDamageReceived","damagePlayerPair","sourceId","filteredPlayerDamages","damage","attrReceivedFromCommanderPlayerId","makeDefaultGameRoundPlayerDamage","includes","flagLifeLoss","reduce","totalDamage","flagLifeGain","life","flagStartingLife","isEliminatedByForce","flagIsEliminated","some","Boolean","isEliminated","totalCommanderDeaths","flagCommanderDeaths","card","className","animationDelay","userName","user_name","deckName","deck_name","renderCommanderDamageRows","reorderPlayerCards","renderCommanderDamageLog","hookupGameRoundEvents","hookupPlayerCardEvents","getActiveRoundDisplayOrder","damageTableBody","flagDamageLog","newTableBodyHtml","r","p","receivedFromPlayer","attrDamageId","receivedFromCommanderPlayerId","roundId","getActiveRoundId","highestRoundDisplayOrder","acc","cur","filteredRounds","user","attrUserId","activeRoundDisplayOrder","otherPlayer","otherPlayerDisplayName","curr","isLethal","incrementRoundButtonSelector","flagRoundDisplayOrderButton","amount","flagRoundDisplayOrderPlus","roundDisplayOrderButtonContainer","newDisplayOrder","displayOrder","lifeGainButtonSelector","activeRoundId","damageIndex","findIndex","changeLife","lifeLossButtonSelector","commanderDeathButtonSelector","isMinusButton","changeCommanderDeaths","commmanderDamageButtonSelector","changeCommanderDamage","eliminatePlayerButtonSelector","toggleEliminate","isLifeGainNotLoss","updateDamage","lifeInput","lifeDisplay","currentLife","newLife","damageInput","damageDisplay","currentDamage","newDamage","damageRecord","deathDisplay","currentDeaths","newDeaths","eliminateBtn","wasEliminated","playerGrid","currentPlayerCards","newPlayerCards","playerCardMetas","playerCard","newPlayerGridInnerHTML","playerIdA","playerIdB","isEliminatedAsIntA","isEliminatedAsIntB","playerA","playerB","indexPlayerCard","isPlayerEliminated","playerCardMeta","outerHTML","roundDisplayOrder","filteredRoundIds","hasDamageWithIsEliminated","damageFromOtherPlayers","otherPlayerId","maxDamageFromOtherCommander","totalDamageTaken","playerCount","wrapperTemplate","playerSetupWrapperTemplateId","wrapper","wrapperHeading","userDdl","deckDdl","nameInput","makeDefaultGamePlayer","playersToSave","playerSetupWrapper","userId","self","showError","finally","confirm","removeItem","hashPageGames","errorOverlay","errorLabel","_saveTimeout","PageMtgGames","hashPageMtgGames","hookupTcgGames","newGameForm","handleNewGameSubmit","filterForm","handleFilterSubmit","e","hideNewGameForm","modal","newGameButton","showNewGameForm","cancelNewGameButtons","overflow","firstInput","focus","form","reset","formData","FormData","gameType","get","gameData","flagIsDraft","flagIsSealed","flagLocationName","flagStartOn","toISOString","submitBtn","originalText","disabled","games","gamePageHash","hashPageGame","getCSRFToken","metaTag","hiddenInput","cookies","cookie","showSuccess","joinGame","deleteGame","result","animation","setTimeout","PageMtgHome","hashPageMtgHome","hookupTcgHome","PageAccessibilityReport","hashPageAccessibilityReport","PageAccessibilityStatement","hashPageAccessibilityStatement","PageLicense","hashPageLicense","PagePrivacyPolicy","hashPagePrivacyPolicy","PageRetentionSchedule","hashPageDataRetentionSchedule","MixinPage","pageCurrent","hookupLocalStorage","TableMixinPage","hookupTable","PageUser","hashPageUserAccount","mixin","flagCard","inputFirstname","flagFirstname","inputSurname","flagSurname","inputEmail","flagEmail","idUser","jsonRow","attrUserAuth0Id","flagIsEmailVerified","flagIsSuperUser","flagCanAdminUser","hookupFieldsFirstname","hookupFieldsSurname","hookupFieldsEmail","PageUsers","hashPageUserAccounts","inputNotes","buttonActive","Router","pages","module","routes","loadPage","hashPage","PageClass","getClassPageFromHash","currentPage","pageJson","handlePopState","loadPageCurrent","history","pushState","navigateToUrl","appendHistory","loadPageBodyFromResponse","App","dom","setupEventListeners","start","handleGlobalClick","initPageCurrent","app","domReady","fn","readyState"],"sourceRoot":""} \ No newline at end of file diff --git a/static/js/api.js b/static/js/api.js index aff81fe..168a95f 100644 --- a/static/js/api.js +++ b/static/js/api.js @@ -81,6 +81,13 @@ export default class API { } // MTG Game API methods + static async getIsGameDataOutdated(game) { + const url = `/mtg/api/game/${game[attrGameId]}/is-outdated`; + let dataRequest = {}; + dataRequest[flagGame] = game; + return await API.request(url, 'POST', dataRequest); + } + static async saveGame(game, formFilters, comment) { let dataRequest = {}; dataRequest[flagFormFilters] = DOM.convertForm2JSON(formFilters); diff --git a/static/js/pages/tcg/mtg_game.js b/static/js/pages/tcg/mtg_game.js index d3abfae..5c57159 100644 --- a/static/js/pages/tcg/mtg_game.js +++ b/static/js/pages/tcg/mtg_game.js @@ -4,6 +4,7 @@ import API from "../../api.js"; import TableBasePage from "../base_table.js"; import DOM from "../../dom.js"; import Events from "../../lib/events.js"; +import OverlayConfirm from "../../components/common/temporary/overlay_confirm.js"; export default class PageMtgGame extends TableBasePage { static hash = hashPageMtgGame; @@ -21,6 +22,9 @@ export default class PageMtgGame extends TableBasePage { hookupFilters() { // this.sharedHookupFilters(); } + callFilterTableContent() { + window.location.reload(); + } loadRowTable(rowJson) { return; } @@ -64,6 +68,8 @@ export default class PageMtgGame extends TableBasePage { this.hookupPlayerLifeIncrementButtons(); this.hookupCommanderDamageIncrementButtons(); */ + PageMtgGame.hookupOverlayGameOutdated(); + PageMtgGame.hookupGameUpdateCheck(); } static hookupResetButton() { const resetGameButton = document.querySelector('header.game-header .header-right .btn-tcg.btn-tcg-secondary'); @@ -117,6 +123,55 @@ export default class PageMtgGame extends TableBasePage { } } */ + static hookupGameUpdateCheck() { + const intervalId = setInterval(async () => { + const isGameDataOutdated = await PageMtgGame.checkLastGameUpdate(); + if (isGameDataOutdated) { + clearInterval(intervalId); + } + }, 30000); + } + static async checkLastGameUpdate() { + try { + // Fetch players, rounds, and damage records from API + const isGameDataOutdatedResponse = await API.getIsGameDataOutdated(game); + const isGameDataOutdated = isGameDataOutdatedResponse[flagData]; + console.log({ isGameDataOutdatedResponse, isGameDataOutdated }); + + if (isGameDataOutdated) { + // const gameDataOutdatedLabel = document.querySelector(gameDataOutdatedLabelId); + // gameDataOutdatedLabel.classList.remove(flagIsCollapsed); + const pageTitleElement = document.querySelector('.topnav .tcg-title'); + pageTitleElement.classList.add(flagDirty); + PageMtgGame.showOverlayGameOutdated(); + } + + return isGameDataOutdated; + } catch (error) { + console.error('Error checking for game update from server:', error); + } + } + + static hookupOverlayGameOutdated() { + Events.initialiseEventHandler(idOverlayGameOutdated + ' button.' + flagCancel, flagInitialised, (buttonCancel) => { + buttonCancel.addEventListener('click', () => { + let overlay = document.querySelector(idOverlayGameOutdated); + overlay.style.visibility = 'hidden'; + }); + }); + Events.initialiseEventHandler(idOverlayGameOutdated + ' button.' + flagSubmit, flagInitialised, (buttonConfirm) => { + buttonConfirm.addEventListener('click', () => { + let overlay = document.querySelector(idOverlayGameOutdated); + overlay.style.visibility = 'hidden'; + window.location.reload(); + }); + }); + } + static showOverlayGameOutdated() { + let overlay = document.querySelector(idOverlayGameOutdated); + overlay.classList.remove(flagIsCollapsed); + overlay.style.visibility = 'visible'; + } async loadGameFromServer() { console.log("loading game from server"); @@ -244,7 +299,7 @@ export default class PageMtgGame extends TableBasePage { )) .map(damage => damage[flagLifeLoss] - damage[flagLifeGain]) .reduce((a, b) => a + b, 0); - let life = startingLife - totalDamage; + let life = game[flagStartingLife] - totalDamage; let isEliminatedByForce = damageRecords.filter(damage => ( damage[attrPlayerId] == playerId @@ -482,7 +537,7 @@ export default class PageMtgGame extends TableBasePage { , [flagActive]: true }; } - hookupPlayerCardEvents() { + hookupPlayerCardEvents() { // Life gain buttons let lifeGainButtonSelector = '.life-gain-btn'; Events.hookupEventHandler("click", lifeGainButtonSelector, (event, button) => { @@ -609,7 +664,7 @@ export default class PageMtgGame extends TableBasePage { let isLifeGainNotLoss = false; this.changeLife( playerId // playerId - , -amount // amount + , amount // amount , isLifeGainNotLoss // isLifeGainNotLoss , false // updateDamage , damageIndex // damageIndex @@ -757,7 +812,7 @@ export default class PageMtgGame extends TableBasePage { return ( hasDamageWithIsEliminated || maxDamageFromOtherCommander >= 21 - || totalDamageTaken >= startingLife + || totalDamageTaken >= game[flagStartingLife] ); } @@ -936,6 +991,19 @@ export default class PageMtgGame extends TableBasePage { } } + updateAndToggleShowButtonsSaveCancel() { + // let pageBody = document.querySelector(idPageBody); + let isDirty = DOM.hasDirtyChildrenContainer(pageBody); + + let buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel; + let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave); + let areVisibleSaveCancelButtons = !buttonSave.classList.contains(flagIsCollapsed); + + console.log({ pageBody, isDirty, areVisibleSaveCancelButtons }); + + this.toggleShowButtonsSaveCancel(isDirty || areVisibleSaveCancelButtons); + } + leave() { super.leave(); } diff --git a/templates/layouts/_shared_mtg_scripts.html b/templates/layouts/_shared_mtg_scripts.html index 1a644a4..eebd779 100644 --- a/templates/layouts/_shared_mtg_scripts.html +++ b/templates/layouts/_shared_mtg_scripts.html @@ -25,6 +25,7 @@ var flagLifeLoss = "{{ model.FLAG_LIFE_LOSS }}"; var flagPlayer = "{{ model.FLAG_PLAYER }}"; var flagRound = "{{ model.FLAG_ROUND }}"; + var flagStartingLife = "{{ model.FLAG_STARTING_LIFE }}"; var flagUser = "{{ model.FLAG_USER }}"; var flagValueBool = "{{ model.FLAG_VALUE_BOOL }}"; var flagValueFloat = "{{ model.FLAG_VALUE_FLOAT }}"; diff --git a/templates/layouts/_shared_scripts.html b/templates/layouts/_shared_scripts.html index 4c9c672..be95bd6 100644 --- a/templates/layouts/_shared_scripts.html +++ b/templates/layouts/_shared_scripts.html @@ -40,6 +40,7 @@ var flagContainerInput = "{{ model.FLAG_CONTAINER_INPUT }}"; {# var flagContainerSaveCancelButtons = "{{ model.FLAG_CONTAINER_SAVE_CANCEL_BUTTONS }}"; #} var flagCsrfToken = "{{ model.FLAG_CSRF_TOKEN }}"; + var flagData = "{{ model.FLAG_DATA }}"; var flagDdlPreview = "{{ model.FLAG_DDL_PREVIEW }}"; var flagDelete = "{{ model.FLAG_DELETE }}"; var flagDescription = "{{ model.FLAG_DESCRIPTION }}"; diff --git a/templates/pages/tcg/mtg/_game.html b/templates/pages/tcg/mtg/_game.html index d7dc7ad..e84f332 100644 --- a/templates/pages/tcg/mtg/_game.html +++ b/templates/pages/tcg/mtg/_game.html @@ -174,29 +174,43 @@ {% include 'components/common/temporary/_overlay_confirm.html' %} {% include 'components/common/temporary/_overlay_error.html' %} + + diff --git a/todo.txt b/todo.txt index 304b6f1..df8af16 100644 --- a/todo.txt +++ b/todo.txt @@ -1,11 +1,26 @@ Winner of game animation - bring to centre with trophy icon and show updates player + deck stats (+ charts?), add end time -Game start + end times left / right of game location + Deck mulligan rate - add to player table and then just get statistics whenever wanted Ensure no duplicate players by Game ID and User ID and Deck ID -player save with null name not pulling user and deck names -create damage from commander fills is_eliminated with false, but create from player's own damage leaves is_eliminated undefined +Track counters + - settings / advanced customisation section at game creation to toggle which counters are visible -Change round - update player cards to show damage at that point for easier editing +Track mana pool during turn + +dice roll feature + +REPLACE VARCHAR WITH TEXT + , INTEGER WITH INT + +share button on game page, deck page + +# Hardware project +undo last change - display for button for a few seconds after knob stops moving +Components: +1x Knob display +1x 134N3P LiPo power bank module +1x 1000mAh LiPo battery +1x USB-C charger (not included) \ No newline at end of file