1732 lines
80 KiB
PHP
1732 lines
80 KiB
PHP
<?php
|
|
|
|
ini_set('display_errors', 1);
|
|
ini_set('display_startup_errors', 1);
|
|
|
|
if (!isset($baseDir)) {
|
|
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
}
|
|
|
|
require_once $baseDir . '/../scripts/session_functions.php';
|
|
|
|
ini_wkvs_session(true);
|
|
|
|
$csrf_token = $_SESSION['csrf_token'] ?? '';
|
|
|
|
$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;
|
|
|
|
if (!$access_granted_wkl):
|
|
|
|
$logintype = 'wk_leitung';
|
|
|
|
require $baseDir . '/../scripts/login/login.php';
|
|
|
|
$logintype = '';
|
|
|
|
else:
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="de">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<link rel="icon" type="png" href="/intern/img/icon.png">
|
|
<title>WK-leitung - Rank Live</title>
|
|
|
|
|
|
<link rel="stylesheet" href="/intern/css/rank-live.css">
|
|
<link rel="stylesheet" href="/intern/css/sidebar.css">
|
|
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
|
|
<script src="/intern/js/jquery/jquery-ui.min.js"></script>
|
|
<script src="/intern/js/jquery/jquery.ui.touch-punch.min.js"></script>
|
|
<script src="/intern/js/custom-msg-display.js"></script>
|
|
<link rel="stylesheet" href="/intern/css/custom-msg-display.css">
|
|
<link rel="stylesheet" href="/intern/css/custom-select.css">
|
|
<link rel="stylesheet" href="/files/fonts/fonts.css">
|
|
<link rel="stylesheet" href="/intern/css/user.css">
|
|
|
|
<link rel="stylesheet" href="/intern/css/coloris/coloris.min.css" />
|
|
<script src="/intern/js/coloris/coloris.min.js"></script>
|
|
|
|
</head>
|
|
|
|
<body class="einstellungen">
|
|
<?php
|
|
|
|
|
|
require $baseDir . '/../scripts/db/db-functions.php';
|
|
require $baseDir . '/../scripts/db/db-tables.php';
|
|
|
|
require $baseDir . '/../scripts/websocket/ws-create-token.php';
|
|
|
|
|
|
$type = 'wkl';
|
|
|
|
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
|
|
|
if ($dbconnection['success'] !== true) {
|
|
echo 'Critical DB Error.';
|
|
exit;
|
|
}
|
|
|
|
$currentPage = 'rankLive';
|
|
|
|
require $baseDir . '/../scripts/sidebar/sidebar.php';
|
|
|
|
$active_slug = $_SESSION['current_ranklive_slug'] ?? 'rankLive-overview';
|
|
|
|
$allNotenTypes = db_select($mysqli, $db_tabelle_wertungstypen, "name, id, anzahl_laeufe_json");
|
|
$indexed_noten = array_column($allNotenTypes, "name", "id");
|
|
|
|
$geraeteDB = db_select($mysqli, $db_tabelle_disziplinen, "id, name");
|
|
$geraete = array_column($geraeteDB, "name", "id");
|
|
$geraete[0] = 'Pseudogerät für Berechnung';
|
|
$total_geraete_count = count($geraete) - 1;
|
|
|
|
$programme_db = db_select($mysqli, $db_tabelle_kategorien, "id, programm");
|
|
$programme = array_column($programme_db, "programm", "id");
|
|
$total_programs_count = count($programme);
|
|
|
|
$all_program_ids = array_keys($programme);
|
|
|
|
$options_note = [];
|
|
$options_note_s_geraet = [];
|
|
|
|
foreach ($allNotenTypes as $s_note) {
|
|
$id = $s_note['id'];
|
|
$anzahl_laeufe_array = json_decode($s_note['anzahl_laeufe_json'] ?? '', true) ?? [];
|
|
$default = intval($anzahl_laeufe_array['default'] ?? 1);
|
|
|
|
$runs_per_device = [];
|
|
|
|
foreach ($geraete as $g_id => $s_geraet) {
|
|
$sub_default = $anzahl_laeufe_array[$g_id]['all'] ?? $default;
|
|
$is_g_specific = isset($anzahl_laeufe_array[$g_id]['all']);
|
|
|
|
foreach ($programme as $p_id => $s_prog) {
|
|
$is_p_specific = isset($anzahl_laeufe_array[$g_id][$p_id]) && !is_array($anzahl_laeufe_array[$g_id][$p_id]);
|
|
$k = $is_p_specific ? intval($anzahl_laeufe_array[$g_id][$p_id]) : $sub_default;
|
|
|
|
if ($k < 1) continue;
|
|
if ($g_id === 0 && !($is_p_specific || $is_g_specific)) continue;
|
|
|
|
for ($i = 1; $i <= $k; $i++) {
|
|
$options_note[$id][$g_id][$i][$p_id] = 1;
|
|
}
|
|
}
|
|
|
|
$runs_per_device[$g_id] = isset($options_note[$id][$g_id]) ? count($options_note[$id][$g_id]) : 0;
|
|
}
|
|
|
|
if (isset($options_note[$id])) {
|
|
foreach ($options_note[$id] as $g_id => $g_array) {
|
|
foreach ($g_array as $run => $run_array) {
|
|
if (count($run_array) === $total_programs_count) {
|
|
$options_note[$id][$g_id][$run] = ['A'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$max = max($runs_per_device);
|
|
for ($i = 1; $i <= $max; $i++) {
|
|
foreach ($runs_per_device as $g_id => $run_c) {
|
|
if ($run_c < $i) continue;
|
|
$options_note_s_geraet[$id][$i][$g_id] = 1;
|
|
}
|
|
}
|
|
|
|
if (isset($options_note_s_geraet[$id])) {
|
|
foreach ($options_note_s_geraet[$id] as $run => $g_array) {
|
|
$has_zero = isset($g_array[0]);
|
|
$expected_count = $has_zero ? $total_geraete_count + 1 : $total_geraete_count;
|
|
|
|
if (count($g_array) === $total_geraete_count && !$has_zero) {
|
|
$options_note_s_geraet[$id][$run] = 'A';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$getGeraetName = function($id) use ($geraete) {
|
|
return $geraete[$id] ?? '';
|
|
};
|
|
|
|
|
|
|
|
$allOptions = [
|
|
'text' => [
|
|
'text' => 'Eigener statischer Text'
|
|
],
|
|
'personData' => [
|
|
'geburtsdatum' => 'Geburtsdatum',
|
|
'jahrgang' => 'Jahrgang',
|
|
'name' => 'Name',
|
|
'vorname' => 'Vorname',
|
|
'verein' => 'Verein',
|
|
'programm' => 'Programm'
|
|
],
|
|
'sortData' => [
|
|
'rang' => 'Rang',
|
|
'startindex' => 'Startreihenfolge'
|
|
],
|
|
'layoutEls' => [
|
|
'vertical' => 'Vertical'
|
|
],
|
|
'kampfrichterEls' => [
|
|
'edit' => 'Bearbeitungsicon'
|
|
],
|
|
'notenData' => $options_note,
|
|
'notenGeraetData' => $options_note_s_geraet
|
|
];
|
|
|
|
$allOprionsNameArray = [
|
|
'text' => 'Statischer Text',
|
|
'personData' => 'Personendaten',
|
|
'sortData' => 'Rangdaten',
|
|
'notenData' => 'Noten',
|
|
'notenGeraetData' => 'Noten',
|
|
'layoutEls' => 'Layout Elemente',
|
|
'kampfrichterEls' => 'Elemente Kampfrichter'
|
|
];
|
|
|
|
$jsonstr = db_select($mysqli, $db_tabelle_tabellen_konfiguration, 'json', 'type_slug = ?', [$active_slug], '', 1);
|
|
|
|
$allowed_types = [
|
|
'rankLive-overview' => ["name" => 'RankLive Overview', 'geraet' => 'all', 'type' => 'rankLive'],
|
|
'rankLive-geraet' => ["name" => 'RankLive einzelnes Gerät', 'geraet' => 'single', 'type' => 'rankLive'],
|
|
'kampfrichter-admin' => ["name" => 'Kampfrichter Admin (alle Geräte)', 'geraet' => 'all', 'type' => 'kampfrichter'],
|
|
'kampfrichter-geraet' => ["name" => 'Kampfrichter einzelnes Gerät', 'geraet' => 'single', 'type' => 'kampfrichter'],
|
|
'rangliste' => ["name" => 'Rangliste', 'geraet' => 'all', 'type' => 'indev']
|
|
];
|
|
|
|
// 2. Decode JSON into an associative array
|
|
$data = json_decode($jsonstr[0]['json'] ?? '', true) ?? [];
|
|
|
|
$headers = $data['header'] ?? [];
|
|
$bodyColumns = $data['body'] ?? [];
|
|
|
|
function ipn($input)
|
|
{
|
|
global $programme;
|
|
return $programme[$input] ?? '';
|
|
}
|
|
|
|
$lindex = 0;
|
|
$highest_uid = 0;
|
|
|
|
function constructSingleValueSpan($token, $type) {
|
|
global $lindex;
|
|
global $highest_uid;
|
|
$lindex++;
|
|
$text = $token['text'] ?? '';
|
|
$uid = (int) ($token['uid'] ?? 0);
|
|
|
|
if ($uid > $highest_uid) $highest_uid = $uid;
|
|
|
|
$classes = 'singleValueSpan ui-sortable-handle dragable';
|
|
$extraAttributes = '';
|
|
$boldString = '';
|
|
$minDisplayWidth = $token['minDisplayWidth'] ?? 0;
|
|
$dataAttributes = 'data-min-display-width="' . $minDisplayWidth . '" data-uid="' . $uid . '" data-type="' . htmlspecialchars($type) . '"';
|
|
$style = '';
|
|
|
|
|
|
|
|
if ($type !== 'kampfrichterEls') {
|
|
$bold = $token['bold'] ?? false;
|
|
$font_size = $token['fontSize'] ?? 0;
|
|
$linked_el_uid = $token['linkedElUid'] ?? 0;
|
|
|
|
if ($font_size > 0) {
|
|
$style = ' style="font-size: ' . (int)$font_size . 'px"';
|
|
}
|
|
|
|
$boldString = ($bold === true || $bold === 'true') ? 'true' : 'false';
|
|
$dataAttributes .= ' data-bold="' . $boldString . '" data-linked-el-uid="' . $linked_el_uid . '"';
|
|
}
|
|
|
|
|
|
|
|
switch ($type) {
|
|
case 'text':
|
|
$classes .= ' staticText';
|
|
$dataAttributes .= ' data-column="' . htmlspecialchars($token['column'] ?? 'text') . '"';
|
|
break;
|
|
|
|
case 'kampfrichterEls':
|
|
$dataAttributes .= ' data-column="' . htmlspecialchars($token['column'] ?? 'text') . '"';
|
|
break;
|
|
|
|
case 'personData':
|
|
$dataAttributes .= ' data-column="' . htmlspecialchars($token['column'] ?? '') . '"';
|
|
|
|
if (($token['column'] ?? '') === 'geburtsdatum') {
|
|
$dataAttributes .= ' data-php-date-format="' . htmlspecialchars($token['phpDateFormat'] ?? '') . '"';
|
|
}
|
|
break;
|
|
|
|
case 'notenData':
|
|
$dataAttributes .= ' data-field-type-id="' . htmlspecialchars($token['field-type-id'] ?? '') . '"';
|
|
$dataAttributes .= ' data-geraet-id="' . htmlspecialchars($token['geraet-id'] ?? '') . '"';
|
|
$dataAttributes .= ' data-run="' . htmlspecialchars($token['run'] ?? '') . '"';
|
|
$dataAttributes .= ' data-programm-ids="' . htmlspecialchars($token['programm-ids'] ?? '') . '"';
|
|
|
|
$notenNullable = $token['notenNullable'] ?? false;
|
|
$notenNullableStr = ($notenNullable === 'true' || $notenNullable === true) ? 'true' : 'false';
|
|
$dataAttributes .= ' data-noten-nullable="' . $notenNullableStr . '"';
|
|
break;
|
|
|
|
case 'notenGeraetData':
|
|
$dataAttributes .= ' data-field-type-id="' . htmlspecialchars($token['field-type-id'] ?? '') . '"';
|
|
$dataAttributes .= ' data-run="' . htmlspecialchars($token['run'] ?? '') . '"';
|
|
|
|
$notenNullable = $token['notenNullable'] ?? false;
|
|
$notenNullableStr = ($notenNullable === 'true' || $notenNullable === true) ? 'true' : 'false';
|
|
$dataAttributes .= ' data-noten-nullable="' . $notenNullableStr . '"';
|
|
break;
|
|
|
|
case 'sortData':
|
|
$dataAttributes .= ' data-column="' . htmlspecialchars($token['column'] ?? '') . '"';
|
|
break;
|
|
}
|
|
?>
|
|
<span class="<?= $classes; ?>" <?= $dataAttributes; ?><?= $extraAttributes; ?><?= $style ?>>
|
|
<span class="textSingleValueSpan"><?= htmlspecialchars($text) ?></span>
|
|
|
|
<div class="settingsDivSingleValueSpan hidden">
|
|
<?php if ($type === 'text') : ?>
|
|
<div class="settingsInputGroup">
|
|
<label for="statischerTextInput-<?= $lindex ?>">Text:</label>
|
|
<input type="text"
|
|
id="statischerTextInput-<?= $lindex ?>"
|
|
class="statischerTextInput"
|
|
placeholder="Statischer Text"
|
|
value="<?= htmlspecialchars($text) ?>">
|
|
</div>
|
|
<?php elseif ($type === 'notenData' || $type === 'notenGeraetData') : ?>
|
|
<div class="settingsInputGroup">
|
|
<label for="nullNotenCheckbox-<?= $lindex ?>">Wert 0.00 <b>nicht</b> anzeigen?</label>
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
id="nullNotenCheckbox-<?= $lindex ?>"
|
|
class="nullNotenCheckbox"
|
|
<?= ($notenNullable === 'true' || $notenNullable === true) ? 'checked' : '' ?>>
|
|
<span class="checkbox-ui"></span>
|
|
</label>
|
|
</div>
|
|
<?php elseif ($type === 'personData' && ($token['column'] ?? '') === 'geburtsdatum') : ?>
|
|
<div class="settingsInputGroup">
|
|
<label for="gebutsdatumFormatInput-<?= $lindex ?>"><a href="https://www.php.net/manual/de/datetime.format.php#:~:text=format,-Das" target="_blank">PHP-Datumsformat</a></label>
|
|
<div class="autocomplete-container">
|
|
<input type="text" id="gebutsdatumFormatInput-<?= $lindex ?>" class="gebutsdatumFormatInput" value="<?= htmlspecialchars($token['phpDateFormat'] ?? '') ?>" placeholder="d. MMMM YYYY">
|
|
<div id="dropdownList" class="dropdown-list hidden"></div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($type !== 'kampfrichterEls') : ?>
|
|
<div class="settingsInputGroup">
|
|
<label for="boldCheckbox-<?= $lindex ?>">Fetter Text:</label>
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
id="boldCheckbox-<?= $lindex ?>"
|
|
class="boldCheckbox"
|
|
<?= ($bold === 'true' || $bold === true) ? 'checked' : '' ?>>
|
|
<span class="checkbox-ui"></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="settingsInputGroup">
|
|
<label for="inputFontSize-<?= $lindex ?>">Schriftgrösse</label>
|
|
<label for="inputFontSize-<?= $lindex ?>" class="inputLabelWrapper">
|
|
<input type="number"
|
|
min="1"
|
|
id="inputFontSize-<?= $lindex ?>"
|
|
class="inputFontSize"
|
|
placeholder="16"
|
|
value="<?= ($font_size > 0) ? (int)$font_size : ''?>">
|
|
<span>px</span>
|
|
</label>
|
|
|
|
</div>
|
|
|
|
<div class="settingsInputGroup">
|
|
<label for="inputDisplayOnDisplayWidth-<?= $lindex ?>">Minimale Bildschirmbreite</label>
|
|
<label for="inputDisplayOnDisplayWidth-<?= $lindex ?>" class="inputLabelWrapper">
|
|
<input type="number"
|
|
placeholder="Kein Limit"
|
|
class="inputDisplayOnDisplayWidth"
|
|
id="inputDisplayOnDisplayWidth-<?= $lindex ?>"
|
|
value="<?= intval($minDisplayWidth) ?>">
|
|
<span>px</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="settingsInputGroup">
|
|
<label for="inputConditionalDisplay-<?= $lindex ?>">Conditional Display</label>
|
|
<button type="button" id="inputConditionalDisplay-<?= $lindex ?>" class="inputConditionalDisplay">
|
|
Element auswählen…
|
|
</button>
|
|
<span class="spanConditionalDisplay"></span>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="settingsInputGroup">
|
|
<label for="deleteSingleValueSpan-<?= $lindex ?>">Löschen</label>
|
|
<button type="button"
|
|
id="deleteSingleValueSpan-<?= $lindex ?>"
|
|
class="deleteSingleValueSpan">X</button>
|
|
</div>
|
|
</div>
|
|
<span class="settingSpan">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1a8.45 8.45 0 0 0-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3-1.57-3-3.5s1.07-3.5 3-3.5 3 1.57 3 3.5-1.07 3.5-3 3.5z"></path>
|
|
</svg>
|
|
</span>
|
|
</span>
|
|
<?php }
|
|
|
|
?>
|
|
<section class="bgSection">
|
|
<?php sidebarRender('modal'); ?>
|
|
<div class="headerDivTrainer">
|
|
<div class="headingPanelDiv">
|
|
<h2 class="headingPanel">Konfiguration RankLive</h2>
|
|
</div>
|
|
<div class="menuWrapper">
|
|
<?php sidebarRender('button'); ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="dashboardGrid">
|
|
<div class="selectSlugType">
|
|
<div class="customSelect customSelectSlugType" id="selectedOptionSlugType" data-value="">
|
|
<button type="button" id="selectTriggerSlugType" class="selectTrigger paddingNormal" aria-expanded="false">
|
|
<span class="selectLabel"><?= $allowed_types[$active_slug]['name'] ?? '' ?></span>
|
|
<svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'
|
|
height="14" width="14">
|
|
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round'
|
|
stroke-linejoin='round' />
|
|
</svg>
|
|
</button>
|
|
<ul class="selectOptions">
|
|
|
|
<?php foreach ($allowed_types as $s_type => $s_type_data): ?>
|
|
<?php $selected = ($s_type === $active_slug) ? 'selected' : ''; ?>
|
|
<li data-value="<?= htmlspecialchars($s_type) ?>" data-type="<?= htmlspecialchars($s_type_data['type']) ?>" data-geraet="<?= htmlspecialchars($s_type_data['geraet']) ?>" class="<?= $selected ?>"><?= htmlspecialchars($s_type_data['name']) ?></li>
|
|
<?php endforeach; ?>
|
|
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="contentDiv">
|
|
<table class="mainTable">
|
|
<thead>
|
|
<tr id="headerRowRankLiveConfig">
|
|
<?php foreach ($headers as $header_data): ?>
|
|
<?php
|
|
$minDisplayWidth = intval($header_data['minDisplayWidth'] ?? 0);
|
|
$lindex++;
|
|
?>
|
|
<th class="headerThRankLiveConfig" data-min-display-width="<?= $minDisplayWidth ?>">
|
|
<span>
|
|
<input class="columnTitleInput" placeholder="Spaltenüberschrift" value="<?= htmlspecialchars($header_data['title']) ?>">
|
|
<span class="deleteColumnBtn">X</span>
|
|
<span class="addColumnBtn addColumnBtnAfter">+</span>
|
|
<span class="addColumnBtn addColumnBtnBefore">+</span>
|
|
<div class="settingsDivSingleValueSpan hidden">
|
|
|
|
<div class="settingsInputGroup">
|
|
<label for="inputDisplayOnDisplayWidth-<?= $lindex ?>">Minimale Bildschirmbreite</label>
|
|
<label for="inputDisplayOnDisplayWidth-<?= $lindex ?>" class="inputLabelWrapper">
|
|
<input type="number"
|
|
placeholder="Kein Limit"
|
|
class="inputDisplayOnDisplayWidth"
|
|
id="inputDisplayOnDisplayWidth-<?= $lindex ?>"
|
|
value="<?= intval($minDisplayWidth) ?>">
|
|
<span>px</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<span class="settingSpan">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1a8.45 8.45 0 0 0-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3-1.57-3-3.5s1.07-3.5 3-3.5 3 1.57 3 3.5-1.07 3.5-3 3.5z"></path>
|
|
</svg>
|
|
</span>
|
|
</span>
|
|
</th>
|
|
<?php endforeach; ?>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr id="bodyRowRankLiveConfig">
|
|
<?php foreach ($bodyColumns as $columnTokens): ?>
|
|
<td>
|
|
<span class="rankLiveFieldContainer dragableDropArea">
|
|
<span class="addFieldBtn">+</span>
|
|
|
|
<?php
|
|
|
|
foreach ($columnTokens as $token) {
|
|
$type = $token['type'] ?? '';
|
|
if ($type === 'layoutEls') :
|
|
$column = $token['column'];
|
|
$content = $token['content'] ?? []; ?>
|
|
<div class="<?= $column ?>LayoutEl dragable" data-type="<?= $type ?>" data-column="<?= $column ?>">
|
|
<?php foreach ($content as $row) : ?>
|
|
<span class="dragableDropArea <?= $column ?>LayoutElRow">
|
|
<?php foreach ($row as $el) :
|
|
constructSingleValueSpan($el, $el['type']);
|
|
endforeach; ?>
|
|
</span>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php else:
|
|
constructSingleValueSpan($token, $type);
|
|
endif;
|
|
}
|
|
|
|
?>
|
|
|
|
</span>
|
|
</td>
|
|
<?php endforeach; ?>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<button id="addColumn" class="blackBtn <?= count($headers) > 0 ? 'hidden' : '' ?>">Spalte hinzufügen</button>
|
|
<label for="importConfig" class="blackBtn">Tablelle importieren</label>
|
|
<input id="importConfig" type="file" class="hidden" accept=".json, .wkvs">
|
|
<button id="exportConfig" class="blackBtn">Gespeicherte Tablelle exportieren</button>
|
|
<button id="saveConfig" class="blackBtn">Tablelle speichern</button>
|
|
</div>
|
|
<div class="inDevDiv">Dieses Feature befindet sich zurzeit noch in Entwicklung</div>
|
|
</div>
|
|
|
|
<div class="customSelect customSelectAddOption hidden" id="selectedOption" data-value="">
|
|
<button type="button" id="selectTrigger" class="selectTrigger paddingNormal" aria-expanded="false">
|
|
<span class="selectLabel placeholder">Bitte auswählen…</span>
|
|
<svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'
|
|
height="14" width="14">
|
|
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round'
|
|
stroke-linejoin='round' />
|
|
</svg>
|
|
</button>
|
|
<ul class="selectOptions">
|
|
|
|
<?php foreach ($allOptions as $sNotenGroupName => $sNotenGroup): ?>
|
|
<div class="singleOptionDiv <?= $sNotenGroupName ?>">
|
|
<li class="customSelectSubGroupHeader"><?= $allOprionsNameArray[$sNotenGroupName] ?></li>
|
|
<ul class="customSelectSubGroup">
|
|
<?php foreach ($sNotenGroup as $key => $sNote): ?>
|
|
<?php if ($sNotenGroupName === 'notenData'): ?>
|
|
<?php foreach ($sNote as $g_id => $n_array_gerate): ?>
|
|
<?php foreach ($n_array_gerate as $run => $n_array_run): ?>
|
|
|
|
<?php
|
|
|
|
$has_all_progs = !(is_array($n_array_run) && !(isset($n_array_run[0]) && $n_array_run[0] === 'A'));
|
|
$displayed_progs = $has_all_progs ? '' : ' (nur ' . implode(', ', array_map('ipn', array_keys($n_array_run))) . ')';
|
|
$data_progs = $has_all_progs ? 'A' : '[' . implode(', ', array_keys($n_array_run)) . ']';
|
|
$runs = count($n_array_gerate) > 1 ? ' (Run ' . $run . ')' : '';
|
|
$geraet = (intval($g_id) !== 0) ? ', ' . ($geraete[$g_id] ?? 'INTERNAL ERROR') : '';
|
|
|
|
?>
|
|
|
|
<li data-field-type-id="<?= $key ?>" data-type="<?= $sNotenGroupName ?>"
|
|
data-geraet-id="<?= $g_id ?>" data-run="<?= $run ?>" data-programm-ids="<?= $data_progs ?>"
|
|
class=""><?= $indexed_noten[$key] ?><?= $geraet ?><?= $runs ?><?= $displayed_progs ?></li>
|
|
|
|
<?php endforeach; ?>
|
|
<?php endforeach; ?>
|
|
<?php elseif ($sNotenGroupName === 'notenGeraetData'):
|
|
$note_name = $indexed_noten[$key] ?? '';
|
|
$multiple_runs = count($sNote) > 1;
|
|
|
|
foreach ($sNote as $run => $run_geraete):
|
|
|
|
$run_text = ($multiple_runs) ? " R". $run : '';
|
|
$geraete_text = (is_array($run_geraete) && !empty($run_geraete)) ? " (nur " . implode(", ", array_map($getGeraetName, array_keys($run_geraete))) . ")" : "";
|
|
|
|
?>
|
|
|
|
<li data-field-type-id="<?= $key ?>" data-type="<?= $sNotenGroupName ?>"
|
|
data-run="<?= $run ?>"
|
|
class=""><?= $note_name ?><?= $run_text ?><?= $geraete_text ?></li>
|
|
|
|
<?php endforeach; ?>
|
|
<?php else: ?>
|
|
<li data-column="<?= $key ?>" data-type="<?= $sNotenGroupName ?>" class=""><?= $sNote ?></li>
|
|
<?php endif; ?>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="msgDiv"></div>
|
|
|
|
</section>
|
|
|
|
<script>
|
|
|
|
const arrayWSSend = [
|
|
''
|
|
];
|
|
|
|
let $activeEl = null;
|
|
let active_type_slug = '<?= $active_slug ?>';
|
|
let currentUid = <?= $highest_uid + 1 ?>;
|
|
|
|
const $customSelectColumns = $('.customSelectAddOption');
|
|
const $headerRow = $('#headerRowRankLiveConfig');
|
|
const $bodyRow = $('#bodyRowRankLiveConfig');
|
|
const csrf_token = "<?= $csrf_token ?>";
|
|
|
|
$(document).on('click', '.selectTrigger', function (e) {
|
|
e.stopPropagation();
|
|
$(this).closest('.customSelect').toggleClass('open');
|
|
});
|
|
|
|
function setDropdownWidth() {
|
|
const $container = $('.customSelectAddOption');
|
|
|
|
const $dropdown = $container.children('.selectOptions');
|
|
|
|
const width = $dropdown.outerWidth();
|
|
|
|
if (width === 0) width = 100;
|
|
$container.outerWidth(width);
|
|
}
|
|
|
|
const $uids = $('.singleValueSpan:not([data-uid="0"])');
|
|
|
|
const arrayUids = $uids.map(function() {
|
|
return parseInt($(this).data('uid'), 10) || 0;
|
|
}).get();
|
|
|
|
let currentCheckId = arrayUids.length > 0 ? Math.max(...arrayUids) + 1 : 1;
|
|
|
|
function getNextAvailableUid() {
|
|
let candidateId = currentCheckId;
|
|
|
|
while (arrayUids.includes(candidateId)) {
|
|
candidateId++;
|
|
}
|
|
|
|
arrayUids.push(candidateId);
|
|
|
|
currentCheckId = candidateId + 1;
|
|
|
|
return candidateId;
|
|
}
|
|
|
|
function setNullUids() {
|
|
const $targetEls = $('.singleValueSpan[data-uid="0"]');
|
|
if ($targetEls.length < 1) return;
|
|
|
|
$targetEls.each((index, el) => {
|
|
$(el).attr('data-uid', getNextAvailableUid());
|
|
});
|
|
}
|
|
|
|
setNullUids();
|
|
|
|
function setDropdownPosition(el) {
|
|
const $button = $(el);
|
|
|
|
const $td = $button.closest('td');
|
|
|
|
if ($td.length === 0) {
|
|
console.error("Could not find parent <td> element.");
|
|
return;
|
|
}
|
|
|
|
let pos = $td.offset();
|
|
const $tdHeightOffset = $td.outerHeight() + 5;
|
|
|
|
pos.top = pos.top + $tdHeightOffset;
|
|
pos.left = pos.left - 1;
|
|
|
|
$('.customSelectAddOption').css({
|
|
top: pos.top,
|
|
left: pos.left
|
|
}).data('button', el);
|
|
}
|
|
|
|
$(window).on('resize', function() {
|
|
let reference = $('.customSelectAddOption').data('button') ?? null;
|
|
|
|
if (reference === null) return;
|
|
|
|
const $reference = $(reference);
|
|
|
|
const $td = $reference.closest('td');
|
|
|
|
if ($td.length === 0) {
|
|
console.error("Could not find parent <td> element.");
|
|
return;
|
|
}
|
|
|
|
let pos = $td.offset();
|
|
const $tdHeightOffset = $td.outerHeight() + 5;
|
|
|
|
pos.top = pos.top + $tdHeightOffset;
|
|
pos.left = pos.left - 1;
|
|
|
|
$('.customSelectAddOption').css({
|
|
top: pos.top,
|
|
left: pos.left
|
|
})
|
|
})
|
|
|
|
const $table = $('mainTable');
|
|
|
|
function settingsSvg() {
|
|
return $('<span></span>').addClass('settingSpan').html('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1a8.45 8.45 0 0 0-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3-1.57-3-3.5s1.07-3.5 3-3.5 3 1.57 3 3.5-1.07 3.5-3 3.5z"/></svg>');
|
|
}
|
|
|
|
function generateTh() {
|
|
const $newTh = $("<th></th>").addClass('headerThRankLiveConfig');
|
|
|
|
const $newThSpan = $("<span></span>");
|
|
|
|
const $deleteBtn = $("<span></span>").text("X").addClass('deleteColumnBtn');
|
|
|
|
const $addSpanAfter = $("<span></span>").text("+").addClass('addColumnBtn addColumnBtnAfter').data("insert", "after");
|
|
const $addSpanBefore = $("<span></span>").text("+").addClass('addColumnBtn addColumnBtnBefore').data("insert", "before");
|
|
|
|
const $input = $('<input>').attr('placeholder', 'Spaltenüberschrift').addClass('columnTitleInput');
|
|
|
|
const $div = $('<div></div>').addClass('settingsDivSingleValueSpan hidden');
|
|
|
|
/*const $boldDiv = $('<div></div>').addClass('settingsInputGroup');
|
|
const $label1 = $('<label></label>').text('Fetter Text:').attr('for', `boldCheckbox-${lindex}`);
|
|
const $input1 = createCheckbox('boldCheckbox', `boldCheckbox-${lindex}`);
|
|
$boldDiv.append($label1, $input1);
|
|
|
|
const $fontSizeDiv = $('<div></div>').addClass('settingsInputGroup');
|
|
const $labelFontSize = $('<label></label>').text('Schriftgrösse').attr('for', `inputFontSize-${lindex}`);
|
|
const $inputFontSize = $('<input>').attr('placeholder', '16').attr("type", "number").addClass('inputFontSize').attr('id', `inputFontSize-${lindex}`).attr("min", "1");
|
|
const $pxSpanFontSize = $('<span></span>').text('px');
|
|
const $labelWraperFontSize = $('<label></label>').class("inputLabelWrapper").attr('for', `inputFontSize-${lindex}`);
|
|
$labelWraperFontSize.append($inputFontSize, $pxSpanFontSize);
|
|
$fontSizeDiv.append($labelFontSize, $labelWraperFontSize);*/
|
|
|
|
const $mobileDiv = $('<div></div>').addClass('settingsInputGroup');
|
|
const $labelM = $('<label></label>').text('Minimale Bildschirmbreite').attr('for', `inputDisplayOnDisplayWidth-${lindex}`);
|
|
const $inputM = $('<input>').attr('placeholder', 'Kein Limit').attr("type", "number").addClass('inputDisplayOnDisplayWidth').attr('id', `inputDisplayOnDisplayWidth-${lindex}`);
|
|
const $pxSpan = $('<span></span>').text('px');
|
|
const $labelWraper = $('<label></label>').addClass("inputLabelWrapper").attr('for', `inputDisplayOnDisplayWidth-${lindex}`);
|
|
$labelWraper.append($inputM, $pxSpan);
|
|
$mobileDiv.append($labelM, $labelWraper);
|
|
|
|
$div.append($mobileDiv);
|
|
|
|
$newThSpan.append($input, $deleteBtn, $addSpanAfter, $addSpanBefore, $div, settingsSvg());
|
|
|
|
$newTh.append($newThSpan);
|
|
|
|
return $newTh;
|
|
}
|
|
|
|
function generateTd() {
|
|
const $td = $('<td></td>');
|
|
|
|
const $span = $('<span></span>').addClass('rankLiveFieldContainer dragableDropArea');
|
|
|
|
const $addbtn = $('<span></span>').text("+").addClass("addFieldBtn");
|
|
|
|
$span.append($addbtn);
|
|
|
|
$td.append($span);
|
|
|
|
return $td;
|
|
}
|
|
|
|
$('body').on('click', '.addFieldBtn', function (e) {
|
|
$activeEl = $(this).parent();
|
|
|
|
const prevEl = $customSelectColumns.data("last-el") ?? $('body')[0];
|
|
|
|
if (prevEl === this) {
|
|
$customSelectColumns.toggleClass('hidden');
|
|
} else {
|
|
$customSelectColumns.removeClass('hidden');
|
|
}
|
|
|
|
$customSelectColumns.data("last-el", this);
|
|
|
|
if (!$customSelectColumns.hasClass('hidden')) {
|
|
setDropdownWidth();
|
|
setDropdownPosition(this);
|
|
}
|
|
});
|
|
|
|
$('#addColumn').on('click', function (e) {
|
|
$headerRow.append(generateTh());
|
|
|
|
$bodyRow.append(generateTd());
|
|
$(this).addClass('hidden');
|
|
safeRefreshSortable();
|
|
});
|
|
|
|
$('body').on('click', '.addColumnBtn', function (e) {
|
|
|
|
const $el = $(this);
|
|
|
|
const insert = $el.data("insert") ?? '';
|
|
const index = $el.closest('th').index();
|
|
|
|
const $newTh = generateTh();
|
|
|
|
const $existingItemAtIndexHeader = $headerRow.children().eq(index);
|
|
|
|
if ($existingItemAtIndexHeader.length > 0) {
|
|
|
|
if (insert === "before") { $existingItemAtIndexHeader.before($newTh); }
|
|
else { $existingItemAtIndexHeader.after($newTh); }
|
|
|
|
} else {
|
|
$headerRow.append($newTh);
|
|
}
|
|
|
|
const $existingItemAtIndexBody = $bodyRow.children().eq(index);
|
|
|
|
const $newTd = generateTd();
|
|
|
|
if ($existingItemAtIndexBody.length > 0) {
|
|
|
|
if (insert === "before") { $existingItemAtIndexBody.before($newTd); }
|
|
else { $existingItemAtIndexBody.after($newTd); }
|
|
|
|
} else {
|
|
$bodyRow.append($newTd);
|
|
}
|
|
|
|
safeRefreshSortable();
|
|
});
|
|
|
|
$headerRow.sortable({
|
|
connectWith: "#headerRowRankLiveConfig",
|
|
items: ".headerThRankLiveConfig",
|
|
placeholder: "dropPlaceholderColumn",
|
|
helper: "clone",
|
|
appendTo: "body",
|
|
tolerance: "pointer",
|
|
|
|
start: function(e, ui) {
|
|
const elementWidth = ui.item.outerWidth() - 4;
|
|
const elementHeight = ui.item.outerHeight() - 4;
|
|
const oldindex = ui.item.index();
|
|
ui.item.data('old-index', oldindex);
|
|
|
|
ui.placeholder.width(elementWidth);
|
|
ui.placeholder.height(elementHeight);
|
|
},
|
|
|
|
stop: function(e, ui) {
|
|
const oldIndex = ui.item.data('old-index');
|
|
const newIndex = ui.item.index();
|
|
|
|
if (oldIndex === undefined || oldIndex === newIndex) return;
|
|
|
|
const $container = $('#bodyRowRankLiveConfig');
|
|
const $targetTd = $container.children().eq(oldIndex);
|
|
|
|
if ($targetTd.length !== 1) return;
|
|
|
|
if (newIndex > oldIndex) {
|
|
$targetTd.insertAfter($container.children().eq(newIndex));
|
|
} else {
|
|
$targetTd.insertBefore($container.children().eq(newIndex));
|
|
}
|
|
}
|
|
|
|
}).disableSelection();
|
|
|
|
function safeRefreshSortable() {
|
|
$(".dragableDropArea").each(function () {
|
|
if ($(this).data("ui-sortable") || $(this).data("sortable")) {
|
|
$(this).sortable("refresh");
|
|
} else {
|
|
$(this).sortable({
|
|
connectWith: ".dragableDropArea",
|
|
items: ".dragable",
|
|
placeholder: "dropPlaceholder",
|
|
helper: "clone",
|
|
appendTo: "body",
|
|
tolerance: "intersect",
|
|
|
|
start: function(e, ui) {
|
|
const elementWidth = ui.item.outerWidth() - 4;
|
|
const elementHeight = ui.item.outerHeight() - 4;
|
|
|
|
ui.placeholder.width(elementWidth);
|
|
ui.placeholder.height(elementHeight);
|
|
}
|
|
}).disableSelection();
|
|
}
|
|
});
|
|
}
|
|
|
|
safeRefreshSortable();
|
|
|
|
let lindex = <?= $lindex ?? 0 ?>;
|
|
|
|
function createCheckbox(className, id, isChecked = false) {
|
|
|
|
const $label = $('<label>', { class: 'checkbox' });
|
|
|
|
const $input = $('<input>', {
|
|
type: 'checkbox',
|
|
id: id,
|
|
class: className
|
|
});
|
|
|
|
if (isChecked) {
|
|
$input.prop('checked', true);
|
|
}
|
|
|
|
const $span = $('<span>', { class: 'checkbox-ui' });
|
|
|
|
return $label.append($input).append($span);
|
|
}
|
|
|
|
function settingsDiv(type) {
|
|
lindex ++;
|
|
const $div = $('<div></div>').addClass('settingsDivSingleValueSpan hidden');
|
|
|
|
switch (type) {
|
|
case "text":
|
|
const $sdiv1 = $('<div></div>').addClass('settingsInputGroup');
|
|
const $slabel1 = $('<label></label>').text('Text:').attr('for', `statischerTextInput-${lindex}`);
|
|
const $sinput1 = $('<input>').attr('placeholder', 'Statischer Text').addClass('statischerTextInput').attr('id', `statischerTextInput-${lindex}`);
|
|
$sdiv1.append($slabel1, $sinput1);
|
|
$div.append($sdiv1);
|
|
break;
|
|
case "notenData":
|
|
case "notenGeraetData":
|
|
|
|
const $sdiv2 = $('<div></div>').addClass('settingsInputGroup');
|
|
const $slabel2 = $('<label></label>').html('Wert 0.00 <b>nicht</b> anzeigen?').attr('for', `nullNotenCheckbox-${lindex}`);
|
|
const $sinput2 = createCheckbox('nullNotenCheckbox', `nullNotenCheckbox-${lindex}`);
|
|
$sdiv2.append($slabel2, $sinput2);
|
|
$div.append($sdiv2);
|
|
break;
|
|
}
|
|
|
|
if (type !== 'kampfrichterEls') {
|
|
|
|
const $boldDiv = $('<div></div>').addClass('settingsInputGroup');
|
|
const $label1 = $('<label></label>').text('Fetter Text:').attr('for', `boldCheckbox-${lindex}`);
|
|
const $input1 = createCheckbox('boldCheckbox', `boldCheckbox-${lindex}`);
|
|
$boldDiv.append($label1, $input1);
|
|
|
|
const $fontSizeDiv = $('<div></div>').addClass('settingsInputGroup');
|
|
const $labelFontSize = $('<label></label>').text('Schriftgrösse').attr('for', `inputFontSize-${lindex}`);
|
|
const $inputFontSize = $('<input>').attr('placeholder', '16').attr("type", "number").addClass('inputFontSize').attr('id', `inputFontSize-${lindex}`).attr("min", "1");
|
|
const $pxSpanFontSize = $('<span></span>').text('px');
|
|
const $labelWraperFontSize = $('<label></label>').addClass("inputLabelWrapper").attr('for', `inputFontSize-${lindex}`);
|
|
$labelWraperFontSize.append($inputFontSize, $pxSpanFontSize);
|
|
$fontSizeDiv.append($labelFontSize, $labelWraperFontSize);
|
|
|
|
const $mobileDiv = $('<div></div>').addClass('settingsInputGroup');
|
|
const $labelM = $('<label></label>').text('Minimale Bildschirmbreite').attr('for', `inputDisplayOnDisplayWidth-${lindex}`);
|
|
const $inputM = $('<input>').attr('placeholder', 'Kein Limit').attr("type", "number").addClass('inputDisplayOnDisplayWidth').attr('id', `inputDisplayOnDisplayWidth-${lindex}`);
|
|
const $pxSpan = $('<span></span>').text('px');
|
|
const $labelWraper = $('<label></label>').addClass("inputLabelWrapper").attr('for', `inputDisplayOnDisplayWidth-${lindex}`);
|
|
$labelWraper.append($inputM, $pxSpan);
|
|
$mobileDiv.append($labelM, $labelWraper);
|
|
|
|
const $conditionalFormatingDiv = $('<div></div>').addClass('settingsInputGroup');
|
|
const $labelCD = $('<label></label>').text('Conditional Display').attr('for', `inputConditionalDisplay-${lindex}`);
|
|
const $inputCD = $('<button></button>').text('Element auswählen…').attr('type', 'button').addClass('inputConditionalDisplay').attr('id', `inputConditionalDisplay-${lindex}`);
|
|
const $selectedElSpan = $('<span></span>').addClass('spanConditionalDisplay');
|
|
$conditionalFormatingDiv.append($labelCD, $inputCD, $selectedElSpan);
|
|
|
|
$div.append($boldDiv, $fontSizeDiv, $conditionalFormatingDiv, $mobileDiv);
|
|
}
|
|
|
|
const $removeDiv = $('<div></div>').addClass('settingsInputGroup');
|
|
const $labelR = $('<label></label>').text('Löschen').attr('for', `deleteSingleValueSpan-${lindex}`);
|
|
const $inputR = $('<button></button>').text('X').addClass('deleteSingleValueSpan').attr('id', `deleteSingleValueSpan-${lindex}`);
|
|
$removeDiv.append($labelR, $inputR);
|
|
|
|
|
|
$div.append($removeDiv);
|
|
|
|
return $div;
|
|
}
|
|
|
|
$(document).on('click', '.boldCheckbox', function () {
|
|
const $el = $(this);
|
|
const $parent = $el.closest('.singleValueSpan');
|
|
if ($parent.length !== 1) return;
|
|
const oldValue = $parent.attr('data-bold') ?? false;
|
|
const oldBool = oldValue === true || oldValue === 'true';
|
|
$parent.attr('data-bold', !oldBool);
|
|
});
|
|
|
|
$(document).on('click', '.nullNotenCheckbox', function () {
|
|
const $el = $(this);
|
|
const $parent = $el.closest('.singleValueSpan');
|
|
if ($parent.length !== 1) return;
|
|
const oldValue = $parent.attr('data-noten-nullable') ?? false;
|
|
const oldBool = oldValue === true || oldValue === 'true';
|
|
$parent.attr('data-noten-nullable', !oldBool);
|
|
});
|
|
|
|
$(document).on('input', '.statischerTextInput', function () {
|
|
const $el = $(this);
|
|
const val = $el.val();
|
|
const $target = $el.closest('.singleValueSpan').children(".textSingleValueSpan");
|
|
if ($target.length !== 1) return;
|
|
$target.html(val);
|
|
});
|
|
|
|
$(document).on('input', '.inputFontSize', function () {
|
|
const $el = $(this);
|
|
const val = parseInt($el.val(), 10) || 0;
|
|
const $parent = $el.closest('.singleValueSpan');
|
|
if ($parent.length !== 1) return;
|
|
$parent.data('font-size', val);
|
|
const $textSpan = $parent.children('.textSingleValueSpan');
|
|
if ($textSpan.length !== 1) return;
|
|
if (val === 0) {
|
|
$textSpan.css('font-size', '');
|
|
} else {
|
|
$textSpan.css('font-size', val + 'px');
|
|
}
|
|
});
|
|
|
|
$(document).on('input', '.gebutsdatumFormatInput', function () {
|
|
const $el = $(this);
|
|
const val = $el.val();
|
|
const $parent = $el.closest('.singleValueSpan');
|
|
if ($parent.length !== 1) return;
|
|
$parent.data('php-date-format', val);
|
|
});
|
|
|
|
$(document).on('input', '.singleValueSpan .inputDisplayOnDisplayWidth', function () {
|
|
const $el = $(this);
|
|
const val = $el.val();
|
|
const $parent = $el.closest('.singleValueSpan');
|
|
if ($parent.length !== 1) return;
|
|
$parent.attr('data-min-display-width', val);
|
|
});
|
|
|
|
$(document).on('input', 'th .inputDisplayOnDisplayWidth', function () {
|
|
const $el = $(this);
|
|
const val = $el.val();
|
|
const $parent = $el.closest('th');
|
|
if ($parent.length !== 1) return;
|
|
$parent.attr('data-min-display-width', val);
|
|
});
|
|
|
|
$(document).on('click', '.settingSpan', function (e) {
|
|
const $el = $(this);
|
|
const $targetEl = $el.siblings('.settingsDivSingleValueSpan');
|
|
if ($targetEl.length > 0) {
|
|
$targetEl.toggleClass('hidden');
|
|
$('.settingsDivSingleValueSpan').not($targetEl).addClass('hidden');
|
|
} else {
|
|
$('.settingsDivSingleValueSpan').addClass('hidden');
|
|
}
|
|
});
|
|
|
|
function toggleSortable(bool) {
|
|
const sortableText = bool ? "disable" : "enable";
|
|
$(".dragableDropArea").each(function () {
|
|
if ($(this).data("ui-sortable") || $(this).data("sortable")) {
|
|
$(this).sortable(sortableText);
|
|
}
|
|
});
|
|
}
|
|
|
|
$(document).on('click', '.inputConditionalDisplay', function (e) {
|
|
const $btn = $(this);
|
|
const $table = $('table.mainTable');
|
|
if ($table.length !== 1) return;
|
|
|
|
const $container = $btn.closest('.singleValueSpan');
|
|
|
|
if ($container.length !== 1) return;
|
|
|
|
$container.toggleClass('condEl');
|
|
$table.toggleClass('selectCondEl');
|
|
|
|
const tableHasClass = $table.hasClass('selectCondEl');
|
|
toggleSortable(tableHasClass);
|
|
|
|
$('.selectedCondEl').removeClass('selectedCondEl');
|
|
|
|
const savedNativeElUid = $container.attr('data-linked-el-uid') || false;
|
|
if (savedNativeElUid) {
|
|
const $oldSelectedEl = $table.find(`.singleValueSpan[data-uid=${savedNativeElUid}]`);
|
|
if ($oldSelectedEl.length === 1) {
|
|
$oldSelectedEl.addClass('selectedCondEl');
|
|
}
|
|
}
|
|
|
|
if (tableHasClass) {
|
|
$table.on('click.condDisplay', '.singleValueSpan:not(.condEl)', function(e2) {
|
|
const $clickedSpan = $(e2.target).closest('.singleValueSpan');
|
|
|
|
if ($clickedSpan.length !== 1) return;
|
|
|
|
$container.attr('data-linked-el-uid', $clickedSpan.attr('data-uid'));
|
|
|
|
$table.removeClass('selectCondEl');
|
|
$container.removeClass('condEl');
|
|
toggleSortable(false);
|
|
|
|
$table.off('click.condDisplay', '.singleValueSpan:not(.condEl)');
|
|
});
|
|
} else {
|
|
$table.off('click.condDisplay', '.singleValueSpan:not(.condEl)');
|
|
}
|
|
});
|
|
|
|
$(document).on('click', '.deleteSingleValueSpan', async function (e) {
|
|
const $el = $(this);
|
|
const $targetEl = $el.closest('.singleValueSpan');
|
|
|
|
if (!await displayConfirm("Feld löschen?")) return;
|
|
|
|
if ($targetEl.length > 0) {
|
|
$targetEl.remove();
|
|
}
|
|
});
|
|
|
|
|
|
$(document).on('click', '.customSelectAddOption .selectOptions li', function (e) {
|
|
e.stopPropagation();
|
|
const $item = $(this);
|
|
const $container = $item.closest('.customSelect');
|
|
const text = $item.text();
|
|
const $input = $container.find('.selectValue');
|
|
const $textInput = $container.find('.selectText') ?? [];
|
|
const $typeInput = $container.find('.selectType') ?? [];
|
|
const $geraetInput = $container.find('.selectGeraet') ?? [];
|
|
const $label = $container.find('.selectLabel');
|
|
const $allOptions = $container.find('.selectOptions li');
|
|
|
|
$allOptions.removeClass('selected');
|
|
|
|
$input.trigger('change');
|
|
$container.removeClass('open');
|
|
|
|
const type = $item.data("type") ?? null;
|
|
|
|
if (type === 'layoutEls') {
|
|
const $newDiv = $('<div></div>');
|
|
const dataColumn = $item.data("column") ?? null;
|
|
$newDiv.attr("data-column", dataColumn).attr("data-type", type).addClass('dragable');
|
|
|
|
switch (dataColumn) {
|
|
case 'vertical':
|
|
$newDiv.addClass('verticalLayoutEl');
|
|
const $dropSpan = $('<span></span>').addClass('dragableDropArea verticalLayoutElRow');
|
|
$newDiv.append($dropSpan, $dropSpan.clone())
|
|
break;
|
|
}
|
|
$activeEl.append($newDiv);
|
|
} else {
|
|
$span = $('<span></span>').addClass('singleValueSpan dragable').attr("data-type", type).attr('data-uid', getNextAvailableUid());
|
|
currentUid++;
|
|
|
|
const $textSpan = $('<span></span>').text(text).addClass('textSingleValueSpan');
|
|
|
|
if (type === 'notenData') {
|
|
$span.attr("data-geraet-id", $item.data("geraet-id") ?? null);
|
|
$span.attr("data-field-type-id", $item.data("field-type-id") ?? null);
|
|
$span.attr("data-run", $item.data("run") ?? null);
|
|
$span.attr("data-programm-ids", $item.data("programm-ids") ?? null);
|
|
} else if (type === 'notenGeraetData') {
|
|
$span.attr("data-field-type-id", $item.data("field-type-id") ?? null);
|
|
$span.attr("data-run", $item.data("run") ?? null);
|
|
} else {
|
|
$span.attr("data-column", $item.data("column") ?? null);
|
|
}
|
|
|
|
|
|
if (type === 'text') {
|
|
$span.addClass('staticText');
|
|
}
|
|
|
|
$span.append($textSpan, settingsDiv(type), settingsSvg());
|
|
$activeEl.append($span);
|
|
}
|
|
|
|
|
|
$activeEl = null;
|
|
|
|
$customSelectColumns.addClass('hidden');
|
|
|
|
safeRefreshSortable();
|
|
});
|
|
|
|
$(document).on('click', () => $('.customSelect').removeClass('open'));
|
|
|
|
$(document).on('click', function (event) {
|
|
const clickedInsideProtected = $(event.target).closest('.settingSpan, .settingsDivSingleValueSpan, .settingsInputGroup').length > 0;
|
|
|
|
if (clickedInsideProtected) {
|
|
return;
|
|
}
|
|
|
|
$('.settingsDivSingleValueSpan').addClass('hidden');
|
|
});
|
|
|
|
$('body').on('click', '.deleteColumnBtn', async function () {
|
|
|
|
if (!await displayConfirm("Spalte löschen?")) return;
|
|
|
|
const $el = $(this);
|
|
const $th = $el.closest('th');
|
|
|
|
const index = $th.index();
|
|
|
|
const $existingItemAtIndex = $('#bodyRowRankLiveConfig').children().eq(index);
|
|
|
|
if ($existingItemAtIndex.length < 1) {
|
|
displayMsg(0, "Fehler");
|
|
return;
|
|
}
|
|
|
|
$th.remove();
|
|
$existingItemAtIndex.remove();
|
|
showAddBtnOnEmtyHeader();
|
|
});
|
|
|
|
function showAddBtnOnEmtyHeader() {
|
|
if ($('#headerRowRankLiveConfig').children('th').length < 1) $('#addColumn').removeClass('hidden');
|
|
}
|
|
|
|
function generateTargetDataForEl($target, type) {
|
|
|
|
const minDisplayWidth = parseInt($target.attr('data-min-display-width') ?? 0, 10) || 0;
|
|
const elUid = parseInt($target.attr('data-uid') ?? 0, 10) || 0;
|
|
|
|
let targetData = {
|
|
type: type,
|
|
text: $target.children('.textSingleValueSpan').text(),
|
|
minDisplayWidth,
|
|
uid: elUid
|
|
};
|
|
|
|
if (type !== 'kampfrichterEls') {
|
|
const bold = $target.attr('data-bold') ?? false;
|
|
const fontSize = parseInt($target.data('font-size') ?? 0, 10) || 0;
|
|
const condElUid = parseInt($target.attr('data-linked-el-uid') ?? 0, 10) || 0;
|
|
targetData["bold"] = bold;
|
|
targetData["fontSize"] = fontSize;
|
|
targetData["linkedElUid"] = condElUid;
|
|
}
|
|
|
|
|
|
switch (type) {
|
|
case "notenData":
|
|
targetData["field-type-id"] = $target.data('field-type-id');
|
|
targetData["geraet-id"] = $target.data("geraet-id");
|
|
targetData["run"] = $target.data('run');
|
|
targetData["programm-ids"] = $target.data("programm-ids");
|
|
targetData["notenNullable"] = $target.attr("data-noten-nullable") ?? "false";
|
|
break;
|
|
|
|
case "notenGeraetData":
|
|
targetData["field-type-id"] = $target.data('field-type-id');
|
|
targetData["run"] = $target.data('run');
|
|
targetData["notenNullable"] = $target.attr("data-noten-nullable") ?? "false";
|
|
break;
|
|
|
|
case "text":
|
|
targetData.content = $target.data('column');
|
|
break;
|
|
|
|
case "kampfrichterEls":
|
|
targetData.content = $target.data('column');
|
|
break;
|
|
|
|
case "sortData":
|
|
targetData.column = $target.data('column');
|
|
break;
|
|
|
|
case "personData":
|
|
targetData.column = $target.data('column');
|
|
|
|
if ($target.data('column') === 'geburtsdatum') {
|
|
targetData["phpDateFormat"] = $target.data('php-date-format') ?? '';
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return null;
|
|
}
|
|
return targetData;
|
|
}
|
|
|
|
function saveTable() {
|
|
const $headerRow = $('#headerRowRankLiveConfig');
|
|
const $bodyRow = $('#bodyRowRankLiveConfig');
|
|
|
|
const $headerColumns = $headerRow.children('th');
|
|
const $bodyColumns = $bodyRow.children('td');
|
|
|
|
let json = {
|
|
header: [],
|
|
body: []
|
|
};
|
|
|
|
$.each($headerColumns, function (index, el) {
|
|
const $header = $(el);
|
|
const $input = $header.find(".columnTitleInput");
|
|
const val = $input.val() || '';
|
|
const minDisplayWidth = parseInt($header.attr('data-min-display-width') ?? 0, 10) || 0;
|
|
let targetData = {
|
|
title: val,
|
|
minDisplayWidth
|
|
}
|
|
json.header.push(targetData);
|
|
});
|
|
|
|
$.each($bodyColumns, function (index, el) {
|
|
const $targets = $(el).children(".rankLiveFieldContainer").children(":not(.addFieldBtn)");
|
|
|
|
json.body[index] = [];
|
|
|
|
if ($targets.length > 0) {
|
|
$.each($targets, function (tindex, tel) {
|
|
const $target = $(tel);
|
|
const type = $target.data('type');
|
|
|
|
let targetData = {};
|
|
|
|
if (type === 'layoutEls') {
|
|
targetData = {
|
|
type,
|
|
column: $target.attr("data-column"),
|
|
content: []
|
|
};
|
|
const $rows = $target.children(".verticalLayoutElRow");
|
|
|
|
$.each($rows, function (rindex, trow) {
|
|
targetData['content'][rindex] = [];
|
|
|
|
const $row_targets = $(trow).children(".singleValueSpan");
|
|
$.each($row_targets, function (trowindex, trowel) {
|
|
const $trowel = $(trowel);
|
|
const trowelType = $trowel.data('type');
|
|
const subres = generateTargetDataForEl($trowel, trowelType);
|
|
if (subres === null) return null;
|
|
targetData['content'][rindex][trowindex] = subres;
|
|
});
|
|
});
|
|
} else {
|
|
targetData = generateTargetDataForEl($target, type);
|
|
if (targetData === null) return null;
|
|
}
|
|
|
|
json.body[index].push(targetData);
|
|
});
|
|
}
|
|
});
|
|
|
|
const jsonstr = JSON.stringify(json);
|
|
|
|
return jsonstr;
|
|
}
|
|
|
|
$('#saveConfig').on('click', function () {
|
|
const json = saveTable();
|
|
|
|
if (json === null) {
|
|
displayMsg(0, "Fehler beim Konertieren der RankLive Tabelle");
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: '/intern/scripts/ranklive/ajax-save-ranklive-config.php',
|
|
method: 'POST',
|
|
data: {
|
|
csrf_token,
|
|
slug: active_type_slug,
|
|
json: json
|
|
},
|
|
success: function (response) {
|
|
if (typeof response === "string") {
|
|
response = response ? JSON.parse(response) : {};
|
|
}
|
|
|
|
if (response.success) {
|
|
displayMsg(1, "OK");
|
|
} else {
|
|
displayMsg(2, response.message || "Unbekannter Fehler");
|
|
}
|
|
},
|
|
error: function (xhr, status, errorThrown) {
|
|
displayMsg(0, "Fehler");
|
|
console.error(xhr);
|
|
}
|
|
});
|
|
});
|
|
|
|
function loadTable(jsonInput) {
|
|
let json;
|
|
try {
|
|
json = typeof jsonInput === "string" ? JSON.parse(jsonInput) : jsonInput;
|
|
} catch (e) {
|
|
console.error("Invalid JSON provided to loadTable:", e);
|
|
return false;
|
|
}
|
|
|
|
if (!json || !json.header || !json.body) {
|
|
console.error("JSON layout structure is missing header or body blocks.");
|
|
return false;
|
|
}
|
|
|
|
const $headerRow = $('#headerRowRankLiveConfig');
|
|
const $bodyRow = $('#bodyRowRankLiveConfig');
|
|
|
|
$headerRow.empty();
|
|
$bodyRow.empty();
|
|
|
|
$('#addColumn').addClass('hidden');
|
|
|
|
$.each(json.header, function (index, headerData) {
|
|
const $th = generateTh();
|
|
|
|
$th.find('.columnTitleInput').val(headerData.title || '');
|
|
|
|
if (headerData.minDisplayWidth) {
|
|
$th.attr('data-min-display-width', headerData.minDisplayWidth);
|
|
$th.find('.inputDisplayOnDisplayWidth').val(headerData.minDisplayWidth);
|
|
}
|
|
|
|
$headerRow.append($th);
|
|
});
|
|
|
|
$.each(json.body, function (index, columnItems) {
|
|
const $td = generateTd();
|
|
const $container = $td.find('.rankLiveFieldContainer');
|
|
const $addBtn = $container.find('.addFieldBtn');
|
|
|
|
if (columnItems && columnItems.length > 0) {
|
|
$.each(columnItems, function (tindex, itemData) {
|
|
let $element;
|
|
|
|
if (itemData.type === 'layoutEls') {
|
|
$element = $('<div></div>')
|
|
.attr("data-column", itemData.column)
|
|
.attr("data-type", 'layoutEls')
|
|
.addClass('dragable');
|
|
|
|
if (itemData.column === 'vertical') {
|
|
$element.addClass('verticalLayoutEl');
|
|
}
|
|
|
|
if (itemData.content && Array.isArray(itemData.content)) {
|
|
$.each(itemData.content, function (rindex, rowItems) {
|
|
const $dropSpan = $('<span></span>').addClass('dragableDropArea verticalLayoutElRow');
|
|
|
|
if (rowItems && Array.isArray(rowItems)) {
|
|
$.each(rowItems, function (trowindex, subItemData) {
|
|
const $subEl = generateSingleValueSpanFromData(subItemData);
|
|
if ($subEl) $dropSpan.append($subEl);
|
|
});
|
|
}
|
|
$element.append($dropSpan);
|
|
});
|
|
}
|
|
} else {
|
|
$element = generateSingleValueSpanFromData(itemData);
|
|
}
|
|
|
|
if ($element) {
|
|
$addBtn.before($element);
|
|
}
|
|
});
|
|
}
|
|
|
|
$bodyRow.append($td);
|
|
});
|
|
|
|
showAddBtnOnEmtyHeader();
|
|
safeRefreshSortable();
|
|
|
|
return true;
|
|
}
|
|
|
|
// Internal functional helper to systematically convert a single data object back to a DOM node
|
|
function generateSingleValueSpanFromData(data) {
|
|
if (!data || !data.type) return null;
|
|
|
|
const type = data.type;
|
|
const elUid = data.uid || 0;
|
|
const $span = $('<span></span>').addClass('singleValueSpan dragable').attr("data-type", type).attr("data-uid", elUid);
|
|
const $textSpan = $('<span></span>').text(data.text || '').addClass('textSingleValueSpan');
|
|
|
|
// Leverage your existing DOM generator to keep control tracking context unique (lindex)
|
|
const $settings = settingsDiv(type);
|
|
|
|
// Reconstruct Global Layout/Styling Properties
|
|
if (data.bold === true || data.bold === 'true') {
|
|
$span.attr('data-bold', 'true');
|
|
$settings.find('.boldCheckbox').prop('checked', true);
|
|
}
|
|
|
|
if (data.fontSize) {
|
|
const fontSizeVal = parseInt(data.fontSize, 10) || 0;
|
|
$span.data('font-size', fontSizeVal);
|
|
$textSpan.css('font-size', fontSizeVal + 'px');
|
|
$settings.find('.inputFontSize').val(fontSizeVal);
|
|
}
|
|
|
|
if (data.minDisplayWidth) {
|
|
const minWidthVal = parseInt(data.minDisplayWidth, 10) || 0;
|
|
$span.attr('data-min-display-width', minWidthVal);
|
|
$settings.find('.inputDisplayOnDisplayWidth').val(minWidthVal);
|
|
}
|
|
|
|
if (data.linkedElUid) {
|
|
const linkedElUid = parseInt(data.linkedElUid, 10) || 0;
|
|
$span.attr('data-linked-el-uid', linkedElUid);
|
|
}
|
|
|
|
// Reconstruct Context-Specific Metadata Properties
|
|
switch (type) {
|
|
case "notenData":
|
|
case "notenGeraetData":
|
|
const zeroNotenCheck = data["notenNullable"] === true || data["notenNullable"] === 'true';
|
|
$span.attr("data-noten-nullable", zeroNotenCheck ? "true" : "false");
|
|
$settings.find('.nullNotenCheckbox').prop('checked', zeroNotenCheck);
|
|
|
|
case "notenData":
|
|
$span.attr("data-geraet-id", data["geraet-id"] ?? null);
|
|
$span.attr("data-field-type-id", data["field-type-id"] ?? null);
|
|
$span.attr("data-run", data["run"] ?? null);
|
|
$span.attr("data-programm-ids", data["programm-ids"] ?? null);
|
|
break;
|
|
|
|
case "notenGeraetData":
|
|
$span.attr("data-field-type-id", data["field-type-id"] ?? null);
|
|
$span.attr("data-run", data["run"] ?? null);
|
|
break;
|
|
|
|
case "text":
|
|
$span.attr("data-column", data.content ?? null);
|
|
$span.addClass('staticText');
|
|
$settings.find('.statischerTextInput').val(data.text || '');
|
|
break;
|
|
|
|
case "kampfrichterEls":
|
|
$span.attr("data-column", data.content ?? null);
|
|
break;
|
|
|
|
case "personData":
|
|
$span.attr("data-column", data.column ?? null);
|
|
if (data["phpDateFormat"]) {
|
|
$span.data('php-date-format', data["phpDateFormat"]);
|
|
$settings.find('.gebutsdatumFormatInput').val(data["phpDateFormat"]);
|
|
}
|
|
break;
|
|
|
|
case "sortData":
|
|
$span.attr("data-column", data.column ?? null);
|
|
break;
|
|
}
|
|
|
|
$span.append($textSpan, $settings, settingsSvg());
|
|
return $span;
|
|
}
|
|
|
|
const $contentDiv = $('.contentDiv');
|
|
const $inDevDiv = $('.inDevDiv');
|
|
|
|
function configureAddOptionDropdown(type, geraet) {
|
|
|
|
if (type === 'indev' || type === 'rangliste') {
|
|
$contentDiv.addClass('hidden');
|
|
$inDevDiv.removeClass('hidden');
|
|
return;
|
|
}
|
|
|
|
$contentDiv.removeClass('hidden');
|
|
$inDevDiv.addClass('hidden');
|
|
|
|
const $selectOptions = $customSelectColumns.find(".selectOptions");
|
|
if ($selectOptions.length !== 1) return;
|
|
|
|
const $sectionNotenAllData = $selectOptions.find('div.notenData');
|
|
const $sectionNotenGeraetData = $selectOptions.find('div.notenGeraetData');
|
|
|
|
if ($sectionNotenAllData.length !== 1 || $sectionNotenGeraetData.length !== 1) return;
|
|
|
|
const geraetAll = geraet === 'all';
|
|
|
|
$sectionNotenAllData.toggleClass('hidden', !geraetAll);
|
|
$sectionNotenGeraetData.toggleClass('hidden', geraetAll);
|
|
}
|
|
|
|
configureAddOptionDropdown('<?= $allowed_types[$active_slug]['type'] ?>', '<?= $allowed_types[$active_slug]['geraet'] ?>');
|
|
|
|
$(document).on('click', '.customSelectSlugType .selectOptions li', function (e) {
|
|
e.stopPropagation();
|
|
const $item = $(this);
|
|
const $container = $item.closest('.customSelect');
|
|
const text = $item.text();
|
|
const $label = $container.find('.selectLabel');
|
|
const $allOptions = $container.find('.selectOptions li');
|
|
const val = $item.attr('data-value') ?? '';
|
|
const type = $item.attr('data-type') ?? '';
|
|
const geraet = $item.attr('data-geraet') ?? '';
|
|
|
|
$allOptions.removeClass('selected');
|
|
$item.addClass('selected');
|
|
|
|
$label.text(text).removeClass('placeholder');
|
|
$container.removeClass('open');
|
|
|
|
$.ajax({
|
|
url: '/intern/scripts/ranklive/ajax-get-ranklive-config.php',
|
|
method: 'POST',
|
|
data: {
|
|
csrf_token,
|
|
slug: val
|
|
},
|
|
success: function (response) {
|
|
if (typeof response === "string") {
|
|
response = response ? JSON.parse(response) : {};
|
|
}
|
|
|
|
if (!response.success) {
|
|
displayMsg(2, response.message || "Unbekannter Fehler");
|
|
return;
|
|
}
|
|
|
|
active_type_slug = val;
|
|
|
|
$customSelectColumns.addClass('hidden');
|
|
|
|
if (response.data === "") {
|
|
$('#headerRowRankLiveConfig').html('');
|
|
$('#bodyRowRankLiveConfig').html('');
|
|
$('#addColumn').removeClass('hidden');
|
|
} else {
|
|
loadTable(response.data);
|
|
}
|
|
|
|
configureAddOptionDropdown(type, geraet);
|
|
},
|
|
error: function (xhr, status, errorThrown) {
|
|
displayMsg(0, "Fehler");
|
|
console.error(xhr);
|
|
}
|
|
});
|
|
});
|
|
|
|
$('#importConfig').on('change', async function () {
|
|
|
|
if (!await displayConfirm("Die aktuelle Konfiguration wird durch die ausgewählte Datei vollständig überschrieben!")) return;
|
|
|
|
const input = $(this)[0];
|
|
|
|
const formData = new FormData();
|
|
|
|
formData.append('csrf_token', csrf_token);
|
|
formData.append('configFile', input.files[0]);
|
|
formData.append('slug', active_type_slug);
|
|
|
|
$.ajax({
|
|
url: '/intern/scripts/ranklive/upload-config-file.php',
|
|
type: 'POST',
|
|
data: formData,
|
|
processData: false,
|
|
contentType: false,
|
|
success: function (response) {
|
|
response = response ? JSON.parse(response) : {};
|
|
if (response.success) {
|
|
window.location.reload();
|
|
} else {
|
|
if (response.message) {
|
|
displayMsg(0, response.message);
|
|
} else {
|
|
displayMsg(0, "Unbekannter Fehler beim Hochladen der Config-Datei.");
|
|
}
|
|
}
|
|
},
|
|
error: function (xhr, status, errorThrown) {
|
|
let errorMsg = "Kritischer Fehler beim Hochladen der Config-Datei.";
|
|
|
|
if (xhr.responseText) {
|
|
try {
|
|
const response = JSON.parse(xhr.responseText);
|
|
if (response.message) {
|
|
errorMsg = response.message;
|
|
}
|
|
} catch (e) {
|
|
console.error("Could not parse JSON error response:", e);
|
|
}
|
|
}
|
|
|
|
displayMsg(0, errorMsg);
|
|
|
|
console.error(xhr);
|
|
}
|
|
});
|
|
|
|
});
|
|
|
|
$('#exportConfig').on('click', function () {
|
|
$.ajax({
|
|
url: '/intern/scripts/ranklive/export-config-file.php',
|
|
method: 'POST',
|
|
data: {
|
|
csrf_token: csrf_token,
|
|
slug: active_type_slug
|
|
},
|
|
dataType: 'text',
|
|
success: function(response, status, xhr) {
|
|
|
|
const disposition = xhr.getResponseHeader('Content-Disposition');
|
|
let filename = `${active_type_slug}.wkvstable`;
|
|
|
|
if (disposition && disposition.indexOf('attachment') !== -1) {
|
|
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
|
|
const matches = filenameRegex.exec(disposition);
|
|
if (matches != null && matches[1]) {
|
|
filename = matches[1].replace(/['"]/g, '');
|
|
}
|
|
}
|
|
|
|
const blob = new Blob([response], { type: 'application/json' });
|
|
|
|
const $tempLink = $('<a>', {
|
|
href: URL.createObjectURL(blob),
|
|
download: filename
|
|
});
|
|
|
|
$('body').append($tempLink);
|
|
$tempLink[0].click();
|
|
|
|
$tempLink.remove();
|
|
URL.revokeObjectURL($tempLink.attr('href'));
|
|
|
|
displayMsg(1, "Tabelle erfolgreich exportiert.");
|
|
},
|
|
error: function(xhr, status, error) {
|
|
displayMsg(0, "Tabelle konnte nicht exportiert werden.");
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
<?php endif; ?>
|