forked from Hay1tsme/artemis
develop #10
@ -1,6 +1,10 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
Documenting updates to ARTEMiS, to be updated every time the master branch is pushed to.
|
Documenting updates to ARTEMiS, to be updated every time the master branch is pushed to.
|
||||||
|
|
||||||
|
## 20240630
|
||||||
|
### DIVA
|
||||||
|
+ Added configurable festa options'
|
||||||
|
|
||||||
## 20240629
|
## 20240629
|
||||||
### CHUNITHM
|
### CHUNITHM
|
||||||
+ Add team points
|
+ Add team points
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
class MainboardPlatformCodes:
|
class MainboardPlatformCodes(Enum):
|
||||||
RINGEDGE = "AALE"
|
RINGEDGE = "AAL"
|
||||||
RINGWIDE = "AAML"
|
RINGEDGE2 = "AAS"
|
||||||
NU = "AAVE"
|
RINGWIDE = "AAM"
|
||||||
NUSX = "AAWE"
|
NU = "AAV"
|
||||||
ALLS_UX = "ACAE"
|
NUSX = "AAW"
|
||||||
ALLS_HX = "ACAX"
|
ALLS = "ACA"
|
||||||
|
#ALLS_UX = "ACAE"
|
||||||
|
#ALLS_HX = "ACAX"
|
||||||
|
|
||||||
|
|
||||||
class MainboardRevisions:
|
class MainboardRevisions(Enum):
|
||||||
RINGEDGE = 1
|
RINGEDGE = 1
|
||||||
RINGEDGE2 = 2
|
RINGEDGE2 = 2
|
||||||
|
|
||||||
@ -29,11 +31,10 @@ class MainboardRevisions:
|
|||||||
ALLS_HX2 = 12
|
ALLS_HX2 = 12
|
||||||
|
|
||||||
|
|
||||||
class KeychipPlatformsCodes:
|
class KeychipPlatformsCodes(Enum):
|
||||||
RING = "A72E"
|
RING = "72"
|
||||||
NU = ("A60E", "A60E", "A60E")
|
NU = ("60", "61", "69")
|
||||||
NUSX = ("A61X", "A69X")
|
ALLS = "63"
|
||||||
ALLS = "A63E"
|
|
||||||
|
|
||||||
|
|
||||||
class AllnetCountryCode(Enum):
|
class AllnetCountryCode(Enum):
|
||||||
|
28
core/data/alembic/versions/5ea73f89d982_card_add_memo.py
Normal file
28
core/data/alembic/versions/5ea73f89d982_card_add_memo.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"""card_add_memo
|
||||||
|
|
||||||
|
Revision ID: 5ea73f89d982
|
||||||
|
Revises: 745448d83696
|
||||||
|
Create Date: 2024-07-06 22:46:56.992152
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '5ea73f89d982'
|
||||||
|
down_revision = '745448d83696'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('aime_card', sa.Column('memo', sa.VARCHAR(length=16), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('aime_card', 'memo')
|
||||||
|
# ### end Alembic commands ###
|
@ -206,17 +206,6 @@ class ArcadeData(BaseData):
|
|||||||
return None
|
return None
|
||||||
return result.lastrowid
|
return result.lastrowid
|
||||||
|
|
||||||
def format_serial( # TODO: Actual serial stuff
|
|
||||||
self, platform_code: str, platform_rev: int, serial_num: int, append: int = 8888
|
|
||||||
) -> str:
|
|
||||||
return f"{platform_code}{platform_rev:02d}A{serial_num:04d}{append:04d}" # 0x41 = A, 0x52 = R
|
|
||||||
|
|
||||||
def validate_keychip_format(self, serial: str) -> bool:
|
|
||||||
if re.fullmatch(r"^A[0-9]{2}[E|X][-]?[0-9]{2}[A-HJ-NP-Z][0-9]{4}([0-9]{4})?$", serial) is None:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
async def get_arcade_by_name(self, name: str) -> Optional[List[Row]]:
|
async def get_arcade_by_name(self, name: str) -> Optional[List[Row]]:
|
||||||
sql = arcade.select(or_(arcade.c.name.like(f"%{name}%"), arcade.c.nickname.like(f"%{name}%")))
|
sql = arcade.select(or_(arcade.c.name.like(f"%{name}%"), arcade.c.nickname.like(f"%{name}%")))
|
||||||
result = await self.execute(sql)
|
result = await self.execute(sql)
|
||||||
@ -230,3 +219,53 @@ class ArcadeData(BaseData):
|
|||||||
if result is None:
|
if result is None:
|
||||||
return None
|
return None
|
||||||
return result.fetchall()
|
return result.fetchall()
|
||||||
|
|
||||||
|
async def get_num_generated_keychips(self) -> Optional[int]:
|
||||||
|
result = await self.execute(select(func.count("serial LIKE 'A69A%'")).select_from(machine))
|
||||||
|
if result:
|
||||||
|
return result.fetchone()['count_1']
|
||||||
|
self.logger.error("Failed to count machine serials that start with A69A!")
|
||||||
|
|
||||||
|
def format_serial(
|
||||||
|
self, platform_code: str, platform_rev: int, serial_letter: str, serial_num: int, append: int, dash: bool = False
|
||||||
|
) -> str:
|
||||||
|
return f"{platform_code}{'-' if dash else ''}{platform_rev:02d}{serial_letter}{serial_num:04d}{append:04d}"
|
||||||
|
|
||||||
|
def validate_keychip_format(self, serial: str) -> bool:
|
||||||
|
# For the 2nd letter, E and X are the only "real" values that have been observed
|
||||||
|
if re.fullmatch(r"^A[0-9]{2}[A-Z][-]?[0-9]{2}[A-HJ-NP-Z][0-9]{4}([0-9]{4})?$", serial) is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Thanks bottersnike!
|
||||||
|
def get_keychip_suffix(self, year: int, month: int) -> str:
|
||||||
|
assert year > 1957
|
||||||
|
assert 1 <= month <= 12
|
||||||
|
|
||||||
|
year -= 1957
|
||||||
|
# Jan/Feb/Mar are from the previous tax year
|
||||||
|
if month < 4:
|
||||||
|
year -= 1
|
||||||
|
assert year >= 1 and year <= 99
|
||||||
|
|
||||||
|
month = ((month - 1) + 9) % 12 # Offset so April=0
|
||||||
|
return f"{year:02}{month // 6:01}{month % 6 + 1:01}"
|
||||||
|
|
||||||
|
|
||||||
|
def parse_keychip_suffix(self, suffix: str) -> tuple[int, int]:
|
||||||
|
year = int(suffix[0:2])
|
||||||
|
half = int(suffix[2])
|
||||||
|
assert half in (0, 1)
|
||||||
|
period = int(suffix[3])
|
||||||
|
assert period in (1, 2, 3, 4, 5, 6)
|
||||||
|
|
||||||
|
month = half * 6 + (period - 1)
|
||||||
|
month = ((month + 3) % 12) + 1 # Offset so Jan=1
|
||||||
|
|
||||||
|
# Jan/Feb/Mar are from the previous tax year
|
||||||
|
if month < 4:
|
||||||
|
year += 1
|
||||||
|
year += 1957
|
||||||
|
|
||||||
|
return (year, month)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
from sqlalchemy import Table, Column, UniqueConstraint
|
from sqlalchemy import Table, Column, UniqueConstraint
|
||||||
from sqlalchemy.types import Integer, String, Boolean, TIMESTAMP, BIGINT
|
from sqlalchemy.types import Integer, String, Boolean, TIMESTAMP, BIGINT, VARCHAR
|
||||||
from sqlalchemy.sql.schema import ForeignKey
|
from sqlalchemy.sql.schema import ForeignKey
|
||||||
from sqlalchemy.sql import func
|
from sqlalchemy.sql import func
|
||||||
from sqlalchemy.engine import Row
|
from sqlalchemy.engine import Row
|
||||||
@ -19,6 +19,7 @@ aime_card = Table(
|
|||||||
Column("last_login_date", TIMESTAMP, onupdate=func.now()),
|
Column("last_login_date", TIMESTAMP, onupdate=func.now()),
|
||||||
Column("is_locked", Boolean, server_default="0"),
|
Column("is_locked", Boolean, server_default="0"),
|
||||||
Column("is_banned", Boolean, server_default="0"),
|
Column("is_banned", Boolean, server_default="0"),
|
||||||
|
Column("memo", VARCHAR(16)),
|
||||||
UniqueConstraint("user", "access_code", name="aime_card_uk"),
|
UniqueConstraint("user", "access_code", name="aime_card_uk"),
|
||||||
mysql_charset="utf8mb4",
|
mysql_charset="utf8mb4",
|
||||||
)
|
)
|
||||||
@ -148,6 +149,11 @@ class CardData(BaseData):
|
|||||||
if not result:
|
if not result:
|
||||||
self.logger.error(f"Failed to change card access code from {old_ac} to {new_ac}")
|
self.logger.error(f"Failed to change card access code from {old_ac} to {new_ac}")
|
||||||
|
|
||||||
|
async def set_memo_by_access_code(self, access_code: str, memo: str) -> None:
|
||||||
|
result = await self.execute(aime_card.update(aime_card.c.access_code == access_code).values(memo=memo))
|
||||||
|
if not result:
|
||||||
|
self.logger.error(f"Failed to add memo to card {access_code}")
|
||||||
|
|
||||||
def to_access_code(self, luid: str) -> str:
|
def to_access_code(self, luid: str) -> str:
|
||||||
"""
|
"""
|
||||||
Given a felica cards internal 16 hex character luid, convert it to a 0-padded 20 digit access code as a string
|
Given a felica cards internal 16 hex character luid, convert it to a 0-padded 20 digit access code as a string
|
||||||
|
@ -476,10 +476,10 @@ class FE_User(FE_Base):
|
|||||||
card_data.append({
|
card_data.append({
|
||||||
'access_code': ac,
|
'access_code': ac,
|
||||||
'status': status,
|
'status': status,
|
||||||
'chip_id': "", #None if c['chip_id'] is None else f"{c['chip_id']:X}",
|
'chip_id': c['chip_id'],
|
||||||
'idm': "",
|
'idm': c['idm'],
|
||||||
'type': c_type,
|
'type': c_type,
|
||||||
"memo": ""
|
"memo": c['memo']
|
||||||
})
|
})
|
||||||
|
|
||||||
if "e" in request.query_params:
|
if "e" in request.query_params:
|
||||||
@ -516,7 +516,42 @@ class FE_User(FE_Base):
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
async def edit_card(self, request: Request) -> RedirectResponse:
|
async def edit_card(self, request: Request) -> RedirectResponse:
|
||||||
return RedirectResponse("/user/", 303)
|
frm = await request.form()
|
||||||
|
usr_sesh = self.validate_session(request)
|
||||||
|
if not usr_sesh or not self.test_perm(usr_sesh.permissions, PermissionOffset.USERMOD):
|
||||||
|
return RedirectResponse("/gate/", 303)
|
||||||
|
|
||||||
|
frm = await request.form()
|
||||||
|
ac = frm.get("add_access_code", None)
|
||||||
|
if not ac:
|
||||||
|
return RedirectResponse("/user/?e=999", 303)
|
||||||
|
|
||||||
|
card = await self.data.card.get_card_by_access_code(ac)
|
||||||
|
if not card:
|
||||||
|
return RedirectResponse("/user/?e=2", 303)
|
||||||
|
|
||||||
|
if card['user'] != usr_sesh.user_id and not self.test_perm_minimum(usr_sesh.permissions, PermissionOffset.USERMOD):
|
||||||
|
return RedirectResponse("/user/?e=11", 303)
|
||||||
|
|
||||||
|
if frm.get("add_memo", None):
|
||||||
|
memo = frm.get("add_memo")
|
||||||
|
if len(memo) > 16 or len(memo) == 0:
|
||||||
|
return RedirectResponse("/user/?e=4", 303)
|
||||||
|
await self.data.card.set_memo_by_access_code(ac, memo)
|
||||||
|
|
||||||
|
if frm.get("add_felica_idm", None):
|
||||||
|
idm = frm.get('add_felica_idm')
|
||||||
|
if not all(c in string.hexdigits for c in idm):
|
||||||
|
return RedirectResponse("/user/?e=4", 303)
|
||||||
|
await self.data.card.set_idm_by_access_code(ac, idm)
|
||||||
|
|
||||||
|
if frm.get("add_mifare_chip_id", None):
|
||||||
|
chip_id: str = frm.get('add_mifare_chip_id')
|
||||||
|
if not all(c in string.hexdigits for c in idm):
|
||||||
|
return RedirectResponse("/user/?e=4", 303)
|
||||||
|
await self.data.card.set_chip_id_by_access_code(ac, int(chip_id, 16))
|
||||||
|
|
||||||
|
return RedirectResponse("/user/?s=4", 303)
|
||||||
|
|
||||||
async def add_card(self, request: Request) -> RedirectResponse:
|
async def add_card(self, request: Request) -> RedirectResponse:
|
||||||
return RedirectResponse("/user/", 303)
|
return RedirectResponse("/user/", 303)
|
||||||
@ -791,14 +826,19 @@ class FE_System(FE_Base):
|
|||||||
return RedirectResponse("/sys/?e=4", 303)
|
return RedirectResponse("/sys/?e=4", 303)
|
||||||
|
|
||||||
if not serial:
|
if not serial:
|
||||||
serial = self.data.arcade.format_serial("A69E", 1, random.randint(1, 9999))
|
append = self.data.arcade.get_keychip_suffix(datetime.now().year, datetime.now().month)
|
||||||
|
generated = await self.data.arcade.get_num_generated_keychips()
|
||||||
|
if not generated:
|
||||||
|
generated = 0
|
||||||
|
serial = self.data.arcade.format_serial("A69A", 1, "A", generated + 1, int(append))
|
||||||
|
serial_dash = self.data.arcade.format_serial("A69A", 1, "A", generated + 1, int(append), True)
|
||||||
|
|
||||||
cab_id = await self.data.arcade.create_machine(int(shopid), serial, None, game_code if game_code else None)
|
cab_id = await self.data.arcade.create_machine(int(shopid), serial, None, game_code if game_code else None)
|
||||||
|
|
||||||
return Response(template.render(
|
return Response(template.render(
|
||||||
title=f"{self.core_config.server.name} | System",
|
title=f"{self.core_config.server.name} | System",
|
||||||
sesh=vars(usr_sesh),
|
sesh=vars(usr_sesh),
|
||||||
cabadd={"id": cab_id, "serial": serial},
|
cabadd={"id": cab_id, "serial": serial_dash},
|
||||||
), media_type="text/html; charset=utf-8")
|
), media_type="text/html; charset=utf-8")
|
||||||
|
|
||||||
async def render_logs(self, request: Request):
|
async def render_logs(self, request: Request):
|
||||||
|
@ -46,7 +46,11 @@ var per_page = 0;
|
|||||||
var page = 0;
|
var page = 0;
|
||||||
|
|
||||||
function update_tbl() {
|
function update_tbl() {
|
||||||
if (TBL_DATA.length == 0) { return; }
|
if (TBL_DATA.length == 0) {
|
||||||
|
document.getElementById("btn_next").disabled = true;
|
||||||
|
document.getElementById("btn_prev").disabled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
var tbl = document.getElementById("tbl_events");
|
var tbl = document.getElementById("tbl_events");
|
||||||
|
|
||||||
for (var i = 0; i < per_page; i++) {
|
for (var i = 0; i < per_page; i++) {
|
||||||
@ -183,7 +187,7 @@ function chg_page(num) {
|
|||||||
document.getElementById("btn_prev").disabled = true;
|
document.getElementById("btn_prev").disabled = true;
|
||||||
return;
|
return;
|
||||||
} else if (page == 0) {
|
} else if (page == 0) {
|
||||||
document.getElementById("btn_next").disabled = false;
|
document.getElementById("btn_next").disabled = TBL_DATA.length == 0;
|
||||||
document.getElementById("btn_prev").disabled = true;
|
document.getElementById("btn_prev").disabled = true;
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("btn_next").disabled = false;
|
document.getElementById("btn_next").disabled = false;
|
||||||
|
@ -49,11 +49,14 @@ function prep_edit_form(access_code, chip_id, idm, card_type, u_memo) {
|
|||||||
fidm.value = idm;
|
fidm.value = idm;
|
||||||
memo.value = u_memo;
|
memo.value = u_memo;
|
||||||
|
|
||||||
if (card_type == "AmusementIC") {
|
if (access_code.startsWith("3") || access_code.startsWith("010")) {
|
||||||
|
cid.disabled = false;
|
||||||
|
fidm.disabled = true;
|
||||||
|
} else if (access_code.startsWith("5")) {
|
||||||
cid.disabled = true;
|
cid.disabled = true;
|
||||||
fidm.disabled = false;
|
fidm.disabled = false;
|
||||||
} else {
|
} else {
|
||||||
cid.disabled = false;
|
cid.disabled = true;
|
||||||
fidm.disabled = true;
|
fidm.disabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,9 +94,14 @@ Card added successfully
|
|||||||
</form>
|
</form>
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
{% if success is defined and success == 4 %}
|
||||||
|
<div style="background-color: #00AA00; padding: 20px; margin-bottom: 10px; width: 15%;">
|
||||||
|
Update successful
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<ul style="font-size: 20px;">
|
<ul style="font-size: 20px;">
|
||||||
{% for c in cards %}
|
{% for c in cards %}
|
||||||
<li>{{ c.access_code }} ({{ c.type}}): {{ c.status }} <button onclick="prep_edit_form('{{ c.access_code }}', '{{ c.chip_id}}', '{{ c.idm }}', '{{ c.type }}', '{{ c.memo }}')" data-bs-toggle="modal" data-bs-target="#card_edit" class="btn btn-secondary" id="btn_edit_card_{{ c.access_code }}">Edit</button> {% if c.status == 'Active'%}<button class="btn-warning btn">Lock</button>{% elif c.status == 'Locked' %}<button class="btn-warning btn">Unlock</button>{% endif %} <button class="btn-danger btn">Delete</button></li>
|
<li>{{ c.access_code }} ({{ c.type if c.memo is none or not c.memo else c.memo }}): {{ c.status }} <button onclick="prep_edit_form('{{ c.access_code }}', '{{ c.chip_id}}', '{{ c.idm }}', '{{ c.type }}', '{{ c.memo }}')" data-bs-toggle="modal" data-bs-target="#card_edit" class="btn btn-secondary" id="btn_edit_card_{{ c.access_code }}">Edit</button> {% if c.status == 'Active'%}<button class="btn-warning btn">Lock</button>{% elif c.status == 'Locked' %}<button class="btn-warning btn">Unlock</button>{% endif %} <button class="btn-danger btn" {{ "disabled" if cards|length == 1 else ""}}>Delete</button></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
data = Data(cfg)
|
data = Data(cfg)
|
||||||
|
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
if args.action == "create":
|
if args.action == "create":
|
||||||
data.create_database()
|
data.create_database()
|
||||||
|
|
||||||
@ -55,19 +57,15 @@ if __name__ == "__main__":
|
|||||||
data.schema_downgrade(args.version)
|
data.schema_downgrade(args.version)
|
||||||
|
|
||||||
elif args.action == "create-owner":
|
elif args.action == "create-owner":
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.run_until_complete(data.create_owner(args.email, args.access_code))
|
loop.run_until_complete(data.create_owner(args.email, args.access_code))
|
||||||
|
|
||||||
elif args.action == "migrate":
|
elif args.action == "migrate":
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.run_until_complete(data.migrate())
|
loop.run_until_complete(data.migrate())
|
||||||
|
|
||||||
elif args.action == "create-revision":
|
elif args.action == "create-revision":
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.run_until_complete(data.create_revision(args.message))
|
loop.run_until_complete(data.create_revision(args.message))
|
||||||
|
|
||||||
elif args.action == "create-autorevision":
|
elif args.action == "create-autorevision":
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.run_until_complete(data.create_revision_auto(args.message))
|
loop.run_until_complete(data.create_revision_auto(args.message))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -269,10 +269,14 @@ the Shop, Modules and Customizations.
|
|||||||
|
|
||||||
Config file is located in `config/diva.yaml`.
|
Config file is located in `config/diva.yaml`.
|
||||||
|
|
||||||
| Option | Info |
|
| Option | Info |
|
||||||
| -------------------- | ----------------------------------------------------------------------------------------------- |
|
| -------------------- | ------------------------------------------------------------------------------------------------ |
|
||||||
| `unlock_all_modules` | Unlocks all modules (costumes) by default, if set to `False` all modules need to be purchased |
|
| `festa_enable` | Enable or disable the ingame festa |
|
||||||
| `unlock_all_items` | Unlocks all items (customizations) by default, if set to `False` all items need to be purchased |
|
| `festa_add_VP` | Set the extra VP you get when clearing a song, if festa is not enabled no extra VP will be given |
|
||||||
|
| `festa_multiply_VP` | Multiplier for festa add VP |
|
||||||
|
| `festa_end_time` | Set the date time for when festa will end and not show up in game anymore |
|
||||||
|
| `unlock_all_modules` | Unlocks all modules (costumes) by default, if set to `False` all modules need to be purchased |
|
||||||
|
| `unlock_all_items` | Unlocks all items (customizations) by default, if set to `False` all items need to be purchased |
|
||||||
|
|
||||||
### Custom PV Lists (databanks)
|
### Custom PV Lists (databanks)
|
||||||
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
server:
|
server:
|
||||||
enable: True
|
enable: True
|
||||||
loglevel: "info"
|
loglevel: "info"
|
||||||
|
festa_enable: True
|
||||||
|
festa_add_VP: "20,5"
|
||||||
|
festa_multiply_VP: "1,2"
|
||||||
|
festa_end_time: "2029-01-01 00:00:00.0"
|
||||||
|
|
||||||
mods:
|
mods:
|
||||||
unlock_all_modules: True
|
unlock_all_modules: True
|
||||||
|
@ -234,11 +234,11 @@ class ChuniFrontend(FE_Base):
|
|||||||
if usr_sesh.user_id > 0:
|
if usr_sesh.user_id > 0:
|
||||||
form_data = await request.form()
|
form_data = await request.form()
|
||||||
chunithm_version = form_data.get("version")
|
chunithm_version = form_data.get("version")
|
||||||
self.logger.info(f"version change to: {chunithm_version}")
|
self.logger.debug(f"version change to: {chunithm_version}")
|
||||||
if(chunithm_version.isdigit()):
|
if(chunithm_version.isdigit()):
|
||||||
usr_sesh.chunithm_version=int(chunithm_version)
|
usr_sesh.chunithm_version=int(chunithm_version)
|
||||||
encoded_sesh = self.encode_session(usr_sesh)
|
encoded_sesh = self.encode_session(usr_sesh)
|
||||||
self.logger.info(f"Created session with JWT {encoded_sesh}")
|
self.logger.debug(f"Created session with JWT {encoded_sesh}")
|
||||||
resp = RedirectResponse("/game/chuni/", 303)
|
resp = RedirectResponse("/game/chuni/", 303)
|
||||||
resp.set_cookie("ARTEMIS_SESH", encoded_sesh)
|
resp.set_cookie("ARTEMIS_SESH", encoded_sesh)
|
||||||
return resp
|
return resp
|
||||||
|
@ -264,6 +264,11 @@ class DivaBase:
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
async def handle_festa_info_request(self, data: Dict) -> Dict:
|
async def handle_festa_info_request(self, data: Dict) -> Dict:
|
||||||
|
if self.game_config.server.festa_enable:
|
||||||
|
festa_end_time = self.game_config.server.festa_end_time
|
||||||
|
else:
|
||||||
|
festa_end_time = (datetime.datetime.now() - datetime.timedelta(days=365)).strftime("%Y-%m-%d %H:%M:%S") + ".0"
|
||||||
|
|
||||||
encoded = "&"
|
encoded = "&"
|
||||||
params = {
|
params = {
|
||||||
"fi_id": "1,2",
|
"fi_id": "1,2",
|
||||||
@ -273,10 +278,10 @@ class DivaBase:
|
|||||||
"fi_difficulty": "-1,-1",
|
"fi_difficulty": "-1,-1",
|
||||||
"fi_pv_id_lst": "ALL,ALL",
|
"fi_pv_id_lst": "ALL,ALL",
|
||||||
"fi_attr": "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
"fi_attr": "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||||
"fi_add_vp": "20,5",
|
"fi_add_vp": f"{self.game_config.server.festa_add_VP}",
|
||||||
"fi_mul_vp": "1,2",
|
"fi_mul_vp": f"{self.game_config.server.festa_multiply_VP}",
|
||||||
"fi_st": "2019-01-01 00:00:00.0,2019-01-01 00:00:00.0",
|
"fi_st": "2019-01-01 00:00:00.0,2019-01-01 00:00:00.0",
|
||||||
"fi_et": "2029-01-01 00:00:00.0,2029-01-01 00:00:00.0",
|
"fi_et": f"{festa_end_time},{festa_end_time}",
|
||||||
"fi_lut": "{self.time_lut}",
|
"fi_lut": "{self.time_lut}",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,29 @@ class DivaServerConfig:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def festa_enable(self) -> bool:
|
||||||
|
return CoreConfig.get_config_field(
|
||||||
|
self.__config, "diva", "server", "festa_enable", default=True
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def festa_add_VP(self) -> str:
|
||||||
|
return CoreConfig.get_config_field(
|
||||||
|
self.__config, "diva", "server", "festa_add_VP", default="20,5"
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def festa_multiply_VP(self) -> str:
|
||||||
|
return CoreConfig.get_config_field(
|
||||||
|
self.__config, "diva", "server", "festa_multiply_VP", default="1,2"
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def festa_end_time(self) -> str:
|
||||||
|
return CoreConfig.get_config_field(
|
||||||
|
self.__config, "diva", "server", "festa_end_time", default="2029-01-01 00:00:00.0"
|
||||||
|
)
|
||||||
|
|
||||||
class DivaModsConfig:
|
class DivaModsConfig:
|
||||||
def __init__(self, parent_config: "DivaConfig") -> None:
|
def __init__(self, parent_config: "DivaConfig") -> None:
|
||||||
|
@ -5,8 +5,9 @@ from starlette.responses import Response, RedirectResponse
|
|||||||
from os import path
|
from os import path
|
||||||
import yaml
|
import yaml
|
||||||
import jinja2
|
import jinja2
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from core.frontend import FE_Base, UserSession
|
from core.frontend import FE_Base, UserSession, PermissionOffset
|
||||||
from core.config import CoreConfig
|
from core.config import CoreConfig
|
||||||
from .database import Mai2Data
|
from .database import Mai2Data
|
||||||
from .config import Mai2Config
|
from .config import Mai2Config
|
||||||
@ -32,6 +33,12 @@ class Mai2Frontend(FE_Base):
|
|||||||
Route("/", self.render_GET_playlog, methods=['GET']),
|
Route("/", self.render_GET_playlog, methods=['GET']),
|
||||||
Route("/{index}", self.render_GET_playlog, methods=['GET']),
|
Route("/{index}", self.render_GET_playlog, methods=['GET']),
|
||||||
]),
|
]),
|
||||||
|
Mount("/events", routes=[
|
||||||
|
Route("/", self.render_events, methods=['GET']),
|
||||||
|
Route("/{event_id:int}", self.render_event_edit, methods=['GET']),
|
||||||
|
Route("/update", self.update_event, methods=['POST']),
|
||||||
|
Route("/version.change", self.version_change, methods=['POST']),
|
||||||
|
]),
|
||||||
Route("/update.name", self.update_name, methods=['POST']),
|
Route("/update.name", self.update_name, methods=['POST']),
|
||||||
Route("/version.change", self.version_change, methods=['POST']),
|
Route("/version.change", self.version_change, methods=['POST']),
|
||||||
]
|
]
|
||||||
@ -44,12 +51,14 @@ class Mai2Frontend(FE_Base):
|
|||||||
if not usr_sesh:
|
if not usr_sesh:
|
||||||
usr_sesh = UserSession()
|
usr_sesh = UserSession()
|
||||||
|
|
||||||
|
incoming_ver = usr_sesh.maimai_version
|
||||||
|
|
||||||
if usr_sesh.user_id > 0:
|
if usr_sesh.user_id > 0:
|
||||||
versions = await self.data.profile.get_all_profile_versions(usr_sesh.user_id)
|
versions = await self.data.profile.get_all_profile_versions(usr_sesh.user_id)
|
||||||
profile = []
|
profile = []
|
||||||
if versions:
|
if versions:
|
||||||
# maimai_version is -1 means it is not initialized yet, select a default version from existing.
|
# maimai_version is -1 means it is not initialized yet, select a default version from existing.
|
||||||
if usr_sesh.maimai_version < 0:
|
if incoming_ver < 0:
|
||||||
usr_sesh.maimai_version = versions[0]['version']
|
usr_sesh.maimai_version = versions[0]['version']
|
||||||
profile = await self.data.profile.get_profile_detail(usr_sesh.user_id, usr_sesh.maimai_version)
|
profile = await self.data.profile.get_profile_detail(usr_sesh.user_id, usr_sesh.maimai_version)
|
||||||
versions = [x['version'] for x in versions]
|
versions = [x['version'] for x in versions]
|
||||||
@ -65,7 +74,7 @@ class Mai2Frontend(FE_Base):
|
|||||||
cur_version=usr_sesh.maimai_version
|
cur_version=usr_sesh.maimai_version
|
||||||
), media_type="text/html; charset=utf-8")
|
), media_type="text/html; charset=utf-8")
|
||||||
|
|
||||||
if usr_sesh.maimai_version >= 0:
|
if incoming_ver < 0:
|
||||||
encoded_sesh = self.encode_session(usr_sesh)
|
encoded_sesh = self.encode_session(usr_sesh)
|
||||||
resp.delete_cookie("ARTEMIS_SESH")
|
resp.delete_cookie("ARTEMIS_SESH")
|
||||||
resp.set_cookie("ARTEMIS_SESH", encoded_sesh)
|
resp.set_cookie("ARTEMIS_SESH", encoded_sesh)
|
||||||
@ -80,12 +89,10 @@ class Mai2Frontend(FE_Base):
|
|||||||
)
|
)
|
||||||
usr_sesh = self.validate_session(request)
|
usr_sesh = self.validate_session(request)
|
||||||
if not usr_sesh:
|
if not usr_sesh:
|
||||||
print("wtf")
|
|
||||||
usr_sesh = UserSession()
|
usr_sesh = UserSession()
|
||||||
|
|
||||||
if usr_sesh.user_id > 0:
|
if usr_sesh.user_id > 0:
|
||||||
if usr_sesh.maimai_version < 0:
|
if usr_sesh.maimai_version < 0:
|
||||||
print(usr_sesh.maimai_version)
|
|
||||||
return RedirectResponse("/game/mai2/", 303)
|
return RedirectResponse("/game/mai2/", 303)
|
||||||
path_index = request.path_params.get('index')
|
path_index = request.path_params.get('index')
|
||||||
if not path_index or int(path_index) < 1:
|
if not path_index or int(path_index) < 1:
|
||||||
@ -175,6 +182,11 @@ class Mai2Frontend(FE_Base):
|
|||||||
if not usr_sesh:
|
if not usr_sesh:
|
||||||
usr_sesh = UserSession()
|
usr_sesh = UserSession()
|
||||||
|
|
||||||
|
if "/events/" in request.url.path:
|
||||||
|
resp = RedirectResponse("/game/mai2/events/", 303)
|
||||||
|
else:
|
||||||
|
resp = RedirectResponse("/game/mai2/", 303)
|
||||||
|
|
||||||
if usr_sesh.user_id > 0:
|
if usr_sesh.user_id > 0:
|
||||||
form_data = await request.form()
|
form_data = await request.form()
|
||||||
maimai_version = form_data.get("version")
|
maimai_version = form_data.get("version")
|
||||||
@ -182,9 +194,108 @@ class Mai2Frontend(FE_Base):
|
|||||||
if(maimai_version.isdigit()):
|
if(maimai_version.isdigit()):
|
||||||
usr_sesh.maimai_version=int(maimai_version)
|
usr_sesh.maimai_version=int(maimai_version)
|
||||||
encoded_sesh = self.encode_session(usr_sesh)
|
encoded_sesh = self.encode_session(usr_sesh)
|
||||||
self.logger.info(f"Created session with JWT {encoded_sesh}")
|
self.logger.debug(f"Created session with JWT {encoded_sesh}")
|
||||||
resp = RedirectResponse("/game/mai2/", 303)
|
|
||||||
resp.set_cookie("ARTEMIS_SESH", encoded_sesh)
|
resp.set_cookie("ARTEMIS_SESH", encoded_sesh)
|
||||||
return resp
|
return resp
|
||||||
else:
|
else:
|
||||||
return RedirectResponse("/gate/", 303)
|
return RedirectResponse("/gate/", 303)
|
||||||
|
|
||||||
|
async def render_events(self, request: Request) -> Response:
|
||||||
|
usr_sesh = self.validate_session(request)
|
||||||
|
if not usr_sesh:
|
||||||
|
return RedirectResponse("/gate/", 303)
|
||||||
|
|
||||||
|
if not self.test_perm(usr_sesh.permissions, PermissionOffset.SYSADMIN):
|
||||||
|
return RedirectResponse("/game/mai2/", 303)
|
||||||
|
|
||||||
|
template = self.environment.get_template(
|
||||||
|
"titles/mai2/templates/events/mai2_events.jinja"
|
||||||
|
)
|
||||||
|
|
||||||
|
incoming_ver = usr_sesh.maimai_version
|
||||||
|
evts = []
|
||||||
|
|
||||||
|
if incoming_ver < 0:
|
||||||
|
usr_sesh.maimai_version = Mai2Constants.VER_MAIMAI_DX
|
||||||
|
|
||||||
|
event_list = await self.data.static.get_game_events(usr_sesh.maimai_version)
|
||||||
|
self.logger.info(f"Get events for v{usr_sesh.maimai_version}")
|
||||||
|
|
||||||
|
for event in event_list:
|
||||||
|
evts.append({
|
||||||
|
"id": event['id'],
|
||||||
|
"version": event['version'],
|
||||||
|
"eventId": event['eventId'],
|
||||||
|
"eventType": event['type'],
|
||||||
|
"name": event['name'],
|
||||||
|
"startDate": event['startDate'].strftime("%x %X"),
|
||||||
|
"enabled": "true" if event['enabled'] else "false",
|
||||||
|
})
|
||||||
|
|
||||||
|
resp = Response(template.render(
|
||||||
|
title=f"{self.core_config.server.name} | {self.nav_name} Events",
|
||||||
|
game_list=self.environment.globals["game_list"],
|
||||||
|
sesh=vars(usr_sesh),
|
||||||
|
version_list=Mai2Constants.VERSION_STRING,
|
||||||
|
events=evts
|
||||||
|
), media_type="text/html; charset=utf-8")
|
||||||
|
|
||||||
|
if incoming_ver < 0:
|
||||||
|
encoded_sesh = self.encode_session(usr_sesh)
|
||||||
|
resp.delete_cookie("ARTEMIS_SESH")
|
||||||
|
resp.set_cookie("ARTEMIS_SESH", encoded_sesh)
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
|
async def render_event_edit(self, request: Request) -> Response:
|
||||||
|
usr_sesh = self.validate_session(request)
|
||||||
|
if not usr_sesh:
|
||||||
|
return RedirectResponse("/gate/", 303)
|
||||||
|
|
||||||
|
if not self.test_perm(usr_sesh.permissions, PermissionOffset.SYSADMIN):
|
||||||
|
return RedirectResponse("/game/mai2/", 303)
|
||||||
|
|
||||||
|
template = self.environment.get_template(
|
||||||
|
"titles/mai2/templates/events/mai2_event_edit.jinja"
|
||||||
|
)
|
||||||
|
|
||||||
|
evt_id = request.path_params.get("event_id")
|
||||||
|
|
||||||
|
event_id = await self.data.static.get_event_by_id(evt_id)
|
||||||
|
if not event_id:
|
||||||
|
return RedirectResponse("/game/mai2/events/", 303)
|
||||||
|
|
||||||
|
return Response(template.render(
|
||||||
|
title=f"{self.core_config.server.name} | {self.nav_name} Edit Event {evt_id}",
|
||||||
|
game_list=self.environment.globals["game_list"],
|
||||||
|
sesh=vars(usr_sesh),
|
||||||
|
user_id=usr_sesh.user_id,
|
||||||
|
version_list=Mai2Constants.VERSION_STRING,
|
||||||
|
cur_version=usr_sesh.maimai_version,
|
||||||
|
event=event_id._asdict()
|
||||||
|
), media_type="text/html; charset=utf-8")
|
||||||
|
|
||||||
|
async def update_event(self, request: Request) -> RedirectResponse:
|
||||||
|
usr_sesh = self.validate_session(request)
|
||||||
|
if not usr_sesh:
|
||||||
|
return RedirectResponse("/gate/", 303)
|
||||||
|
|
||||||
|
if not self.test_perm(usr_sesh.permissions, PermissionOffset.SYSADMIN):
|
||||||
|
return RedirectResponse("/game/mai2/", 303)
|
||||||
|
|
||||||
|
form_data = await request.form()
|
||||||
|
print(form_data)
|
||||||
|
event_id: int = form_data.get("evtId", None)
|
||||||
|
new_enabled: bool = bool(form_data.get("evtEnabled", False))
|
||||||
|
try:
|
||||||
|
new_start_date: datetime = datetime.strptime(form_data.get("evtStart", None), "%Y-%m-%dT%H:%M:%S")
|
||||||
|
except:
|
||||||
|
new_start_date = None
|
||||||
|
|
||||||
|
print(f"{event_id} {new_enabled} {new_start_date}")
|
||||||
|
if event_id is None or new_start_date is None:
|
||||||
|
return RedirectResponse("/game/mai2/events/?e=4", 303)
|
||||||
|
|
||||||
|
await self.data.static.update_event_by_id(int(event_id), new_enabled, new_start_date)
|
||||||
|
|
||||||
|
return RedirectResponse("/game/mai2/events/?s=1", 303)
|
||||||
|
@ -7,6 +7,7 @@ from sqlalchemy.schema import ForeignKey
|
|||||||
from sqlalchemy.sql import func, select
|
from sqlalchemy.sql import func, select
|
||||||
from sqlalchemy.engine import Row
|
from sqlalchemy.engine import Row
|
||||||
from sqlalchemy.dialects.mysql import insert
|
from sqlalchemy.dialects.mysql import insert
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
event = Table(
|
event = Table(
|
||||||
"mai2_static_event",
|
"mai2_static_event",
|
||||||
@ -248,3 +249,18 @@ class Mai2StaticData(BaseData):
|
|||||||
if result is None:
|
if result is None:
|
||||||
return None
|
return None
|
||||||
return result.fetchall()
|
return result.fetchall()
|
||||||
|
|
||||||
|
async def get_event_by_id(self, table_id: int) -> Optional[Row]:
|
||||||
|
result = await self.execute(event.select(event.c.id == table_id))
|
||||||
|
if result:
|
||||||
|
return result.fetchone()
|
||||||
|
|
||||||
|
async def get_events_by_event_id(self, event_id: int) -> Optional[List[Row]]:
|
||||||
|
result = await self.execute(event.select(event.c.eventId == event_id))
|
||||||
|
if result:
|
||||||
|
return result.fetchall()
|
||||||
|
|
||||||
|
async def update_event_by_id(self, table_id: int, is_enable: bool, start_date: datetime) -> None:
|
||||||
|
result = await self.execute(event.update(event.c.id == table_id).values(enabled=is_enable, startDate = start_date))
|
||||||
|
if not result:
|
||||||
|
self.logger.error(f"Failed to update event {table_id} - {is_enable} {start_date}")
|
||||||
|
16
titles/mai2/templates/events/mai2_event_edit.jinja
Normal file
16
titles/mai2/templates/events/mai2_event_edit.jinja
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{% extends "core/templates/index.jinja" %}
|
||||||
|
{% block content %}
|
||||||
|
<!-- TODO: This can probably just be a modal on the main event page -->
|
||||||
|
<form id="frmEvent" method="post" action="/game/mai2/events/update">
|
||||||
|
<h3>Event {{ event.eventId }} for {{ version_list[event.version] }}: {{ event.name }}</h3>
|
||||||
|
<input type="hidden" readonly value="{{event.id}}" id="evtId" name="evtId">
|
||||||
|
<label for="evtEnabled" class="form-label">Enabled</label><br>
|
||||||
|
<input class="form-check-input" type="checkbox" {{ 'checked' if event.enabled else ''}} id="evtEnabled" name="evtEnabled"><br><br>
|
||||||
|
|
||||||
|
<label for="evtStart" class="form-label">Start Date</label><br>
|
||||||
|
<input class="form-input" type="datetime-local" id="evtStart" name="evtStart" value="{{ event.startDate }}"><br><br>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary">Update</button>
|
||||||
|
<button type="cancel" class="btn btn-danger">Delete</button>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
156
titles/mai2/templates/events/mai2_events.jinja
Normal file
156
titles/mai2/templates/events/mai2_events.jinja
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
{% extends "core/templates/index.jinja" %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>Events</h1>
|
||||||
|
<form id="verForm" method="POST" action="/game/mai2/events/version.change">
|
||||||
|
<select id="version" name="version" onchange="updateVer()" form="verForm">
|
||||||
|
{% for ver in range(version_list|length) %}
|
||||||
|
<option value="{{ver}}">{{ version_list[ver] }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
<table class="table table-dark table-striped-columns" id="tbl_events">
|
||||||
|
<caption>Viewing all events</caption>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Version</th>
|
||||||
|
<th>Event ID</th>
|
||||||
|
<th>Event Type</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Start Date</th>
|
||||||
|
<th>Enabled</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% if events is not defined or events|length == 0 %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="11" style="text-align:center"><i>No Events</i></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</table>
|
||||||
|
<div id="div_tbl_ctrl">
|
||||||
|
<select id="sel_per_page" onchange="update_tbl()">
|
||||||
|
<option value="10" selected>10</option>
|
||||||
|
<option value="25">25</option>
|
||||||
|
<option value="50">50</option>
|
||||||
|
<option value="100">100</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button class="btn btn-primary" id="btn_prev" disabled onclick="chg_page(-1)"><<</button>
|
||||||
|
<button class="btn btn-primary" id="btn_next" onclick="chg_page(1)">>></button>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
{% if events is defined %}
|
||||||
|
const TBL_DATA = {{events}};
|
||||||
|
{% else %}
|
||||||
|
const TBL_DATA = [];
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
document.getElementById("version").value = {{ sesh.maimai_version }};
|
||||||
|
|
||||||
|
var per_page = 0;
|
||||||
|
var page = 0;
|
||||||
|
|
||||||
|
function updateVer() {
|
||||||
|
var sel = document.getElementById("version");
|
||||||
|
var frm = document.getElementById("verForm");
|
||||||
|
|
||||||
|
if (sel.value == {{ sesh.maimai_version }}) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frm.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_tbl() {
|
||||||
|
if (TBL_DATA.length == 0) { return; }
|
||||||
|
var tbl = document.getElementById("tbl_events");
|
||||||
|
|
||||||
|
for (var i = 0; i < per_page; i++) {
|
||||||
|
try{
|
||||||
|
tbl.deleteRow(1);
|
||||||
|
} catch {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
per_page = document.getElementById("sel_per_page").value;
|
||||||
|
|
||||||
|
if (per_page >= TBL_DATA.length) {
|
||||||
|
page = 0;
|
||||||
|
document.getElementById("btn_next").disabled = true;
|
||||||
|
document.getElementById("btn_prev").disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < per_page; i++) {
|
||||||
|
let off = (page * per_page) + i;
|
||||||
|
if (off >= TBL_DATA.length) {
|
||||||
|
if (page != 0) {
|
||||||
|
document.getElementById("btn_next").disabled = true;
|
||||||
|
document.getElementById("btn_prev").disabled = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = TBL_DATA[off];
|
||||||
|
var row = tbl.insertRow(i + 1);
|
||||||
|
|
||||||
|
var cell_id = row.insertCell(0);
|
||||||
|
cell_id.innerHTML = data.id;
|
||||||
|
|
||||||
|
var cell_ver = row.insertCell(1);
|
||||||
|
cell_ver.innerHTML = data.version;
|
||||||
|
|
||||||
|
var cell_evtid = row.insertCell(2);
|
||||||
|
cell_evtid.innerHTML = data.eventId;
|
||||||
|
|
||||||
|
var cell_evttype = row.insertCell(3);
|
||||||
|
cell_evttype.innerHTML = data.eventType;
|
||||||
|
|
||||||
|
var cell_name = row.insertCell(4);
|
||||||
|
cell_name.innerHTML = data.name;
|
||||||
|
|
||||||
|
var cell_date = row.insertCell(5);
|
||||||
|
cell_date.innerHTML = data.startDate;
|
||||||
|
|
||||||
|
var call_enabled = row.insertCell(6);
|
||||||
|
if (data.enabled === "true")
|
||||||
|
call_enabled.innerHTML = "✔"
|
||||||
|
else
|
||||||
|
call_enabled.innerHTML = "✖"
|
||||||
|
|
||||||
|
var cell_action = row.insertCell(7);
|
||||||
|
cell_action.innerHTML = "<a href=/game/mai2/events/" + data.id +"><button class='btn btn-primary'>🖉</button></a>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function chg_page(num) {
|
||||||
|
var max_page = TBL_DATA.length / per_page;
|
||||||
|
console.log(max_page);
|
||||||
|
page = page + num;
|
||||||
|
|
||||||
|
|
||||||
|
if (page > max_page && max_page >= 1) {
|
||||||
|
page = max_page;
|
||||||
|
document.getElementById("btn_next").disabled = true;
|
||||||
|
document.getElementById("btn_prev").disabled = false;
|
||||||
|
return;
|
||||||
|
} else if (page < 0) {
|
||||||
|
page = 0;
|
||||||
|
document.getElementById("btn_next").disabled = false;
|
||||||
|
document.getElementById("btn_prev").disabled = true;
|
||||||
|
return;
|
||||||
|
} else if (page == 0) {
|
||||||
|
document.getElementById("btn_next").disabled = false;
|
||||||
|
document.getElementById("btn_prev").disabled = true;
|
||||||
|
} else {
|
||||||
|
document.getElementById("btn_next").disabled = false;
|
||||||
|
document.getElementById("btn_prev").disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_tbl();
|
||||||
|
}
|
||||||
|
|
||||||
|
update_tbl();
|
||||||
|
</script>
|
||||||
|
{% endblock content %}
|
@ -3,6 +3,9 @@
|
|||||||
<ul class="mai2-navi">
|
<ul class="mai2-navi">
|
||||||
<li><a class="nav-link" href="/game/mai2/">PROFILE</a></li>
|
<li><a class="nav-link" href="/game/mai2/">PROFILE</a></li>
|
||||||
<li><a class="nav-link" href="/game/mai2/playlog/">RECORD</a></li>
|
<li><a class="nav-link" href="/game/mai2/playlog/">RECORD</a></li>
|
||||||
|
{% if sesh is defined and sesh is not none and "{:08b}".format(sesh.permissions)[4] == "1" %}
|
||||||
|
<li><a class="nav-link" href="/game/mai2/events/">EVENTS</a></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
@ -12,6 +15,8 @@
|
|||||||
$('.nav-link[href="/game/mai2/"]').addClass('active');
|
$('.nav-link[href="/game/mai2/"]').addClass('active');
|
||||||
} else if (currentPath.startsWith('/game/mai2/playlog/')) {
|
} else if (currentPath.startsWith('/game/mai2/playlog/')) {
|
||||||
$('.nav-link[href="/game/mai2/playlog/"]').addClass('active');
|
$('.nav-link[href="/game/mai2/playlog/"]').addClass('active');
|
||||||
}
|
} {% if sesh is defined and sesh is not none and "{:08b}".format(sesh.permissions)[4] == "1" %}else if (currentPath.startsWith('/game/mai2/events/')) {
|
||||||
|
$('.nav-link[href="/game/mai2/events/"]').addClass('active');
|
||||||
|
} {% endif %}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
Loading…
Reference in New Issue
Block a user