Added TLD update

This commit is contained in:
Pinga 2023-12-11 06:48:03 +02:00
parent 5fc5ffb218
commit 6176b18d55
6 changed files with 632 additions and 9 deletions

View file

@ -31,7 +31,7 @@ class SystemController extends Controller
]);
}
public function manageTlds(Request $request, Response $response)
public function listTlds(Request $request, Response $response)
{
if ($_SESSION["auth_roles"] != 0) {
return $response->withHeader('Location', '/dashboard')->withStatus(302);
@ -39,7 +39,7 @@ class SystemController extends Controller
$db = $this->container->get('db');
return view($response,'admin/system/manageTlds.twig');
return view($response,'admin/system/listTlds.twig');
}
public function createTld(Request $request, Response $response)
@ -344,4 +344,355 @@ class SystemController extends Controller
return view($response,'admin/system/createTld.twig');
}
public function manageTld(Request $request, Response $response, $args)
{
if ($_SESSION["auth_roles"] != 0) {
return $response->withHeader('Location', '/dashboard')->withStatus(302);
}
if ($request->getMethod() === 'POST') {
// Retrieve POST data
$data = $request->getParsedBody();
$db = $this->container->get('db');
if ($args) {
$validators = [
'extension' => v::stringType()->notEmpty()->length(3, 64),
'createm0' => v::numericVal()->between(0.00, 9999999.99, true),
'createm12' => v::numericVal()->between(0.00, 9999999.99, true),
'createm24' => v::numericVal()->between(0.00, 9999999.99, true),
'createm36' => v::numericVal()->between(0.00, 9999999.99, true),
'createm48' => v::numericVal()->between(0.00, 9999999.99, true),
'createm60' => v::numericVal()->between(0.00, 9999999.99, true),
'createm72' => v::numericVal()->between(0.00, 9999999.99, true),
'createm84' => v::numericVal()->between(0.00, 9999999.99, true),
'createm96' => v::numericVal()->between(0.00, 9999999.99, true),
'createm108' => v::numericVal()->between(0.00, 9999999.99, true),
'createm120' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm0' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm12' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm24' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm36' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm48' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm60' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm72' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm84' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm96' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm108' => v::numericVal()->between(0.00, 9999999.99, true),
'renewm120' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm0' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm12' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm24' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm36' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm48' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm60' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm72' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm84' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm96' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm108' => v::numericVal()->between(0.00, 9999999.99, true),
'transferm120' => v::numericVal()->between(0.00, 9999999.99, true),
'restorePrice' => v::numericVal()->between(0.00, 9999999.99, true),
'premiumNamesFile' => v::optional(v::file()->mimetype('text/csv')->size(5 * 1024 * 1024)),
'categoryPrice1' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPrice2' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPrice3' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPrice4' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPrice5' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPrice6' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPrice7' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPrice8' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPrice9' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPrice10' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPriceNew1' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPriceNew2' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPriceNew3' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPriceNew4' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryPriceNew5' => v::optional(v::numericVal()->between(0.00, 9999999.99, true)),
'categoryName1' => v::optional(v::stringType()->length(1, 50)),
'categoryName2' => v::optional(v::stringType()->length(1, 50)),
'categoryName3' => v::optional(v::stringType()->length(1, 50)),
'categoryName4' => v::optional(v::stringType()->length(1, 50)),
'categoryName5' => v::optional(v::stringType()->length(1, 50)),
'categoryName6' => v::optional(v::stringType()->length(1, 50)),
'categoryName7' => v::optional(v::stringType()->length(1, 50)),
'categoryName8' => v::optional(v::stringType()->length(1, 50)),
'categoryName9' => v::optional(v::stringType()->length(1, 50)),
'categoryName10' => v::optional(v::stringType()->length(1, 50)),
'categoryNameNew1' => v::optional(v::stringType()->length(1, 50)),
'categoryNameNew2' => v::optional(v::stringType()->length(1, 50)),
'categoryNameNew3' => v::optional(v::stringType()->length(1, 50)),
'categoryNameNew4' => v::optional(v::stringType()->length(1, 50)),
'categoryNameNew5' => v::optional(v::stringType()->length(1, 50))
];
$errors = [];
foreach ($validators as $field => $validator) {
// If the field is not set and it's optional, skip validation
if (!isset($data[$field]) && strpos($field, 'category') === 0) {
continue;
}
try {
$validator->assert(isset($data[$field]) ? $data[$field] : []);
} catch (\Respect\Validation\Exceptions\NestedValidationException $e) {
$errors[$field] = $e->getMessages();
}
}
if (!empty($errors)) {
// Handle errors
$errorText = '';
foreach ($errors as $field => $messages) {
$errorText .= ucfirst($field) . ' errors: ' . implode(', ', $messages) . '; ';
}
// Trim the final semicolon and space
$errorText = rtrim($errorText, '; ');
$this->container->get('flash')->addMessage('error', $errorText);
return $response->withHeader('Location', '/registry/tld/'.$data['extension'])->withStatus(302);
}
try {
$db->beginTransaction();
$tld_id = $db->selectValue(
'SELECT id FROM domain_tld WHERE tld = ?',
[$data['extension']]
);
$db->update(
'domain_price',
[
'm0' => $data['createm0'],
'm12' => $data['createm12'],
'm24' => $data['createm24'],
'm36' => $data['createm36'],
'm48' => $data['createm48'],
'm60' => $data['createm60'],
'm72' => $data['createm72'],
'm84' => $data['createm84'],
'm96' => $data['createm96'],
'm108' => $data['createm108'],
'm120' => $data['createm120']
],
[
'tldid' => $tld_id,
'command' => 'create'
]
);
$db->update(
'domain_price',
[
'm0' => $data['renewm0'],
'm12' => $data['renewm12'],
'm24' => $data['renewm24'],
'm36' => $data['renewm36'],
'm48' => $data['renewm48'],
'm60' => $data['renewm60'],
'm72' => $data['renewm72'],
'm84' => $data['renewm84'],
'm96' => $data['renewm96'],
'm108' => $data['renewm108'],
'm120' => $data['renewm120']
],
[
'tldid' => $tld_id,
'command' => 'renew'
]
);
$db->update(
'domain_price',
[
'm0' => $data['transferm0'],
'm12' => $data['transferm12'],
'm24' => $data['transferm24'],
'm36' => $data['transferm36'],
'm48' => $data['transferm48'],
'm60' => $data['transferm60'],
'm72' => $data['transferm72'],
'm84' => $data['transferm84'],
'm96' => $data['transferm96'],
'm108' => $data['transferm108'],
'm120' => $data['transferm120']
],
[
'tldid' => $tld_id,
'command' => 'transfer'
]
);
$db->update(
'domain_restore_price',
[
'price' => $data['restorePrice']
],
[
'tldid' => $tld_id
]
);
// Loop through category indices from 1 to 10
for ($i = 1; $i <= 10; $i++) {
$categoryNameKey = 'categoryName' . $i;
$categoryPriceKey = 'categoryPrice' . $i;
// Check if the category name is provided and non-empty
if (!empty($data[$categoryNameKey])) {
$db->update(
'premium_domain_categories',
[
'category_price' => $data[$categoryPriceKey]
],
[
'category_name' => $data[$categoryNameKey]
]
);
}
}
for ($i = 1; $i <= 5; $i++) {
$categoryNameNewKey = 'categoryNameNew' . $i;
$categoryPriceNewKey = 'categoryPriceNew' . $i;
if (isset($data[$categoryNameNewKey]) && isset($data[$categoryPriceNewKey]) && $data[$categoryNameNewKey] !== '' && $data[$categoryPriceNewKey] !== '') {
$db->exec(
'INSERT INTO premium_domain_categories (category_name, category_price) VALUES (?, ?) ON DUPLICATE KEY UPDATE category_price = VALUES(category_price)',
[
$data[$categoryNameNewKey],
$data[$categoryPriceNewKey]
]
);
}
}
$uploadedFiles = $request->getUploadedFiles();
if (!empty($uploadedFiles['premiumNamesFile'])) {
$file = $uploadedFiles['premiumNamesFile'];
// Check if the upload was successful
if ($file->getError() !== UPLOAD_ERR_OK) {
$this->container->get('flash')->addMessage('error', 'Upload failed with error code ' . $file->getError());
return $response->withHeader('Location', '/registry/tld/'.$data['extension'])->withStatus(302);
}
// Validate file type and size
if ($file->getClientMediaType() !== 'text/csv' || $file->getSize() > 5 * 1024 * 1024) {
$this->container->get('flash')->addMessage('error', 'Invalid file type or size');
return $response->withHeader('Location', '/registry/tld/'.$data['extension'])->withStatus(302);
}
// Process the CSV file
$stream = $file->getStream();
$csvContent = $stream->getContents();
$lines = explode(PHP_EOL, $csvContent);
foreach ($lines as $line) {
$data = str_getcsv($line);
if (count($data) >= 2) {
$domainName = $data[0];
$categoryName = $data[1];
// Find the category ID
$categoryResult = $this->db->select("SELECT id FROM premium_domain_categories WHERE category_name = :categoryName", ['categoryName' => $categoryName]);
if ($categoryResult) {
$categoryId = $categoryResult[0]['id'];
// Insert into premium_domain_pricing
$db->exec(
'INSERT INTO premium_domain_pricing (domain_name, category_id) VALUES (?, ?) ON DUPLICATE KEY UPDATE category_id = VALUES(category_id)',
[
$domainName,
$categoryId
]
);
} else {
$this->container->get('flash')->addMessage('error', 'Premium names category ' . $categoryName . ' not found');
return $response->withHeader('Location', '/registry/tld/'.$data['extension'])->withStatus(302);
}
}
}
}
$db->commit();
$this->container->get('flash')->addMessage('success', 'TLD ' . $data['extension'] . ' has been updated successfully');
return $response->withHeader('Location', '/registry/tlds')->withStatus(302);
} catch (Exception $e) {
$db->rollBack();
$this->container->get('flash')->addMessage('error', 'Database failure: ' . $e->getMessage());
return $response->withHeader('Location', '/registry/tld/'.$data['extension'])->withStatus(302);
}
} else {
// Redirect to the tlds view
return $response->withHeader('Location', '/registry/tlds')->withStatus(302);
}
}
$db = $this->container->get('db');
// Get the current URI
$uri = $request->getUri()->getPath();
if ($args) {
$tld = $db->selectRow('SELECT id, tld, idn_table, secure FROM domain_tld WHERE tld = ?',
[ $args ]);
if ($tld) {
$createPrices = $db->selectRow('SELECT * FROM domain_price WHERE tldid = ? AND command = ?', [$tld['id'], 'create']);
$renewPrices = $db->selectRow('SELECT * FROM domain_price WHERE tldid = ? AND command = ?', [$tld['id'], 'renew']);
$transferPrices = $db->selectRow('SELECT * FROM domain_price WHERE tldid = ? AND command = ?', [$tld['id'], 'transfer']);
$tld_restore = $db->selectRow('SELECT * FROM domain_restore_price WHERE tldid = ?',
[ $tld['id'] ]);
$premium_pricing = $db->selectRow('SELECT * FROM premium_domain_pricing WHERE tld_id = ?',
[ $tld['id'] ]);
$premium_categories = $db->select('SELECT * FROM premium_domain_categories');
// Mapping of regex patterns to script names
$regexToScriptName = [
'/^(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-)(.(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-))*$/i' => 'ASCII',
'/^[а-яА-ЯґҐєЄіІїЇѝЍћЋљЈ]+$/u' => 'Cyrillic',
'/^[ぁ-んァ-ン一-龯々]+$/u' => 'Japanese',
'/^[가-힣]+$/u' => 'Korean',
];
$idnRegex = $tld['idn_table']; // Assume this is the regex from the database
$scriptName = '';
// Determine the script name based on the regex
if (array_key_exists($idnRegex, $regexToScriptName)) {
$scriptName = $regexToScriptName[$idnRegex];
} else {
$scriptName = 'Unknown'; // Default or fallback script name
}
return view($response,'admin/system/manageTld.twig', [
'tld' => $tld,
'scriptName' => $scriptName,
'createPrices' => $createPrices,
'renewPrices' => $renewPrices,
'transferPrices' => $transferPrices,
'tld_restore' => $tld_restore,
'premium_pricing' => $premium_pricing,
'premium_categories' => $premium_categories,
'currentUri' => $uri
]);
} else {
// TLD does not exist, redirect to the tlds view
return $response->withHeader('Location', '/registry/tlds')->withStatus(302);
}
} else {
// Redirect to the tlds view
return $response->withHeader('Location', '/registry/tlds')->withStatus(302);
}
}
}

View file

@ -0,0 +1,274 @@
{% extends "layouts/app.twig" %}
{% block title %}{{ __('Manage TLD') }} {{ tld.tld }}{% endblock %}
{% block content %}
<div class="page-wrapper">
<!-- Page header -->
<div class="page-header d-print-none">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
<!-- Page pre-title -->
<div class="page-pretitle">
{{ __('Overview') }}
</div>
<h2 class="page-title">
{{ __('Manage TLD') }} {{ tld.tld }}
</h2>
</div>
</div>
</div>
</div>
<!-- Page body -->
<div class="page-body">
<div class="container-xl">
<div class="col-12">
{% include 'partials/flash.twig' %}
<form action="/registry/tld/{{ tld.tld }}" method="post" autocomplete="off">
{{ csrf.field | raw }}
<div class="card mb-3">
<div class="card-header">
<h5 class="card-title">General Details</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label for="tldName" class="form-label">TLD Extension</label>
<div class="form-control-plaintext">{{ tld.tld }}</div>
<input type="hidden" name="extension" value="{{ tld.tld }}">
</div>
<div class="mb-3">
<label class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="dnssecToggle" disabled>
<span class="form-check-label">DNSSEC</span>
</label>
</div>
<div class="mb-3">
<label for="tldTypeSelector" class="form-label">TLD Type</label>
<div class="form-control-plaintext">ccTLD/gTLD</div>
</div>
<div class="mb-3">
<label for="scriptDropdown" class="form-label">Supported Script</label>
<div class="form-control-plaintext">{{ scriptName }}</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<h5 class="card-title">Pricing</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-vcenter card-table">
<thead>
<tr>
<th>Command</th>
<th>Setup Fee</th>
<th>1 Year <span class="text-red">*</span></th>
<th>2 Years <span class="text-red">*</span></th>
<th>3 Years <span class="text-red">*</span></th>
<th>4 Years <span class="text-red">*</span></th>
<th>5 Years <span class="text-red">*</span></th>
<th>6 Years <span class="text-red">*</span></th>
<th>7 Years <span class="text-red">*</span></th>
<th>8 Years <span class="text-red">*</span></th>
<th>9 Years <span class="text-red">*</span></th>
<th>10 Years <span class="text-red">*</span></th>
</tr>
</thead>
<tbody>
<tr>
<td>Create</td>
<td><input type="number" class="form-control" name="createm0" placeholder="0.00" required min="0" value="{{ createPrices.m0 }}"></td>
<td><input type="number" class="form-control" name="createm12" placeholder="0.00" required min="0" value="{{ createPrices.m12 }}"></td>
<td><input type="number" class="form-control" name="createm24" placeholder="0.00" required min="0" value="{{ createPrices.m24 }}"></td>
<td><input type="number" class="form-control" name="createm36" placeholder="0.00" required min="0" value="{{ createPrices.m36 }}"></td>
<td><input type="number" class="form-control" name="createm48" placeholder="0.00" required min="0" value="{{ createPrices.m48 }}"></td>
<td><input type="number" class="form-control" name="createm60" placeholder="0.00" required min="0" value="{{ createPrices.m60 }}"></td>
<td><input type="number" class="form-control" name="createm72" placeholder="0.00" required min="0" value="{{ createPrices.m72 }}"></td>
<td><input type="number" class="form-control" name="createm84" placeholder="0.00" required min="0" value="{{ createPrices.m84 }}"></td>
<td><input type="number" class="form-control" name="createm96" placeholder="0.00" required min="0" value="{{ createPrices.m96 }}"></td>
<td><input type="number" class="form-control" name="createm108" placeholder="0.00" required min="0" value="{{ createPrices.m108 }}"></td>
<td><input type="number" class="form-control" name="createm120" placeholder="0.00" required min="0" value="{{ createPrices.m120 }}"></td>
</tr>
<tr>
<td>Renew</td>
<td><input type="number" class="form-control" name="renewm0" placeholder="0.00" required min="0" value="{{ renewPrices.m0 }}"></td>
<td><input type="number" class="form-control" name="renewm12" placeholder="0.00" required min="0" value="{{ renewPrices.m12 }}"></td>
<td><input type="number" class="form-control" name="renewm24" placeholder="0.00" required min="0" value="{{ renewPrices.m24 }}"></td>
<td><input type="number" class="form-control" name="renewm36" placeholder="0.00" required min="0" value="{{ renewPrices.m36 }}"></td>
<td><input type="number" class="form-control" name="renewm48" placeholder="0.00" required min="0" value="{{ renewPrices.m48 }}"></td>
<td><input type="number" class="form-control" name="renewm60" placeholder="0.00" required min="0" value="{{ renewPrices.m60 }}"></td>
<td><input type="number" class="form-control" name="renewm72" placeholder="0.00" required min="0" value="{{ renewPrices.m72 }}"></td>
<td><input type="number" class="form-control" name="renewm84" placeholder="0.00" required min="0" value="{{ renewPrices.m84 }}"></td>
<td><input type="number" class="form-control" name="renewm96" placeholder="0.00" required min="0" value="{{ renewPrices.m96 }}"></td>
<td><input type="number" class="form-control" name="renewm108" placeholder="0.00" required min="0" value="{{ renewPrices.m108 }}"></td>
<td><input type="number" class="form-control" name="renewm120" placeholder="0.00" required min="0" value="{{ renewPrices.m120 }}"></td>
</tr>
<tr>
<td>Transfer</td>
<td><input type="number" class="form-control" name="transferm0" placeholder="0.00" required min="0" value="{{ transferPrices.m0 }}"></td>
<td><input type="number" class="form-control" name="transferm12" placeholder="0.00" required min="0" value="{{ transferPrices.m12 }}"></td>
<td><input type="number" class="form-control" name="transferm24" placeholder="0.00" required min="0" value="{{ transferPrices.m24 }}"></td>
<td><input type="number" class="form-control" name="transferm36" placeholder="0.00" required min="0" value="{{ transferPrices.m36 }}"></td>
<td><input type="number" class="form-control" name="transferm48" placeholder="0.00" required min="0" value="{{ transferPrices.m48 }}"></td>
<td><input type="number" class="form-control" name="transferm60" placeholder="0.00" required min="0" value="{{ transferPrices.m60 }}"></td>
<td><input type="number" class="form-control" name="transferm72" placeholder="0.00" required min="0" value="{{ transferPrices.m72 }}"></td>
<td><input type="number" class="form-control" name="transferm84" placeholder="0.00" required min="0" value="{{ transferPrices.m84 }}"></td>
<td><input type="number" class="form-control" name="transferm96" placeholder="0.00" required min="0" value="{{ transferPrices.m96 }}"></td>
<td><input type="number" class="form-control" name="transferm108" placeholder="0.00" required min="0" value="{{ transferPrices.m108 }}"></td>
<td><input type="number" class="form-control" name="transferm120" placeholder="0.00" required min="0" value="{{ transferPrices.m120 }}"></td>
</tr>
</tbody>
</table>
<small class="form-text text-muted">When you type a price for 1 Year above, it will automatically get multiplied for subsequent years.</small>
</div>
<div class="mb-3 mt-3">
<label for="restorePrice" class="form-label required">Restore Price</label>
<input type="number" class="form-control" id="restorePrice" name="restorePrice" placeholder="0.00" required min="0" value="{{ tld_restore.price }}">
<small class="form-text text-muted">Enter the price for restoring the TLD.</small>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<h5 class="card-title">Premium Names</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label for="premiumNamesFile" class="form-label">Upload CSV File</label>
<input type="file" class="form-control" id="premiumNamesFile" name="premiumNamesFile" accept=".csv">
<small class="form-text text-muted">
Please upload a CSV file containing premium names. Each row should include a name and its corresponding pricing category, separated by a comma. Note: If one or more names in the file already exist in our system, they will be overwritten with the new information provided in the upload.
</small>
</div>
<hr>
<h6 class="mt-4 mb-3">Set Premium Name Price Categories</h6>
<table class="table" id="categoriesTable">
<thead>
<tr>
<th>Category Name</th>
<th>Price</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for category in premium_categories %}
<tr>
<td>
<input type="text" class="form-control" name="categoryName{{ category.category_id }}" placeholder="Category Name" value="{{ category.category_name }}">
</td>
<td>
<input type="number" class="form-control" name="categoryPrice{{ category.category_id }}" placeholder="0.00" min="0" value="{{ category.category_price }}">
</td>
<td>
<button type="button" class="btn btn-danger" disabled>-</button>
</td>
</tr>
{% endfor %}
<tr>
<td><input type="text" class="form-control" name="categoryNameNew1" placeholder="New Category 1"></td>
<td><input type="number" class="form-control" name="categoryPriceNew1" placeholder="0.00" min="0"></td>
<td><button type="button" class="btn btn-success add-category">+</button></td>
</tr>
</tbody>
</table>
<small class="form-text text-muted">
Update existing premium categories as needed. Please note: currently, deletion of categories is not available. All updates will modify existing information without removing any categories.
</small>
</div>
<div class="card-footer">
<div class="row align-items-center">
<div class="col-auto">
<button type="submit" class="btn btn-primary">Update TLD {{ tld.tld }}</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<footer class="footer footer-transparent d-print-none">
<div class="container-xl">
<div class="col-12 col-lg-auto mt-3 mt-lg-0">
<ul class="list-inline list-inline-dots mb-0">
<li class="list-inline-item">
Copyright &copy; 2023
<a href="https://namingo.org" target="_blank" class="link-secondary">Namingo</a>.
</li>
</ul>
</div>
</div>
</div>
</footer>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const createm12Input = document.querySelector('input[name="createm12"]');
const renewm12Input = document.querySelector('input[name="renewm12"]');
const transferm12Input = document.querySelector('input[name="transferm12"]');
const updateMultiplication = (input, startColumnIndex, baseInputName) => {
const inputValue = parseFloat(input.value);
if (!isNaN(inputValue)) {
for (let i = startColumnIndex; i <= 10; i++) {
const columnName = `${baseInputName}${12 * i}`;
const columnInput = document.querySelector(`input[name="${columnName}"]`);
if (columnInput) {
columnInput.value = (inputValue * i).toFixed(2);
}
}
}
};
createm12Input.addEventListener('input', () => {
updateMultiplication(createm12Input, 2, 'createm');
});
renewm12Input.addEventListener('input', () => {
updateMultiplication(renewm12Input, 2, 'renewm');
});
transferm12Input.addEventListener('input', () => {
updateMultiplication(transferm12Input, 2, 'transferm');
});
const categoriesTable = document.getElementById('categoriesTable');
const addCategoryButton = document.querySelector('.add-category');
const maxCategories = 5;
let categoryCount = 1;
addCategoryButton.addEventListener('click', function() {
if (categoryCount < maxCategories) {
categoryCount++;
const newRow = document.createElement('tr');
newRow.innerHTML = `
<td><input type="text" class="form-control" name="categoryNameNew${categoryCount}" placeholder="New Category ${categoryCount}"></td>
<td><input type="number" class="form-control" name="categoryPriceNew${categoryCount}" placeholder="0.00" min="0"></td>
<td><button type="button" class="btn btn-danger remove-category">-</button></td>
`;
categoriesTable.querySelector('tbody').appendChild(newRow);
}
if (categoryCount >= maxCategories) {
addCategoryButton.style.display = 'none'; // Disable adding more categories after reaching the limit
}
});
categoriesTable.addEventListener('click', function(event) {
if (event.target.classList.contains('remove-category')) {
const row = event.target.closest('tr');
row.remove();
categoryCount--;
addCategoryButton.style.display = 'block'; // Enable adding more categories after removing one
}
});
});
</script>
{% endblock %}

View file

@ -189,7 +189,7 @@
</a>
</div>
</li>
<li {{ is_current_url('epphistory') or is_current_url('poll') or is_current_url('log') or is_current_url('registry') or is_current_url('reports') or is_current_url('manageTlds') or is_current_url('createTld') ? 'class="nav-item dropdown active"' : 'class="nav-item dropdown"' }}>
<li {{ is_current_url('epphistory') or is_current_url('poll') or is_current_url('log') or is_current_url('registry') or is_current_url('reports') or is_current_url('listTlds') or is_current_url('createTld') or 'tld' in currentUri ? 'class="nav-item dropdown active"' : 'class="nav-item dropdown"' }}>
<a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" data-bs-auto-close="outside" role="button" aria-expanded="false">
<span class="nav-link-icon d-md-none d-lg-inline-block"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z"></path> <path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0"></path></svg>
</span>
@ -201,7 +201,7 @@
<a class="dropdown-item" href="{{route('registry')}}">
{{ __('Configuration') }}
</a>
<a class="dropdown-item" href="{{route('manageTlds')}}">
<a class="dropdown-item" href="{{route('listTlds')}}">
{{ __('TLDs') }}
</a>
<a class="dropdown-item" href="{{route('reports')}}">

View file

@ -23,9 +23,7 @@
}
function actionsFormatter(cell, formatterParams, onRendered) {
return `
<a class="btn btn-outline-yellow" href="/ticket/${cell.getRow().getData().tld}" title="Manage Settings"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 21v-16a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v16l-3 -2l-2 2l-2 -2l-2 2l-2 -2l-3 2" /><path d="M14 8h-2.5a1.5 1.5 0 0 0 0 3h1a1.5 1.5 0 0 1 0 3h-2.5m2 0v1.5m0 -9v1.5" /></svg> Settings</a> <a class="btn btn-outline-info" href="/ticket/${cell.getRow().getData().tld}" title="Manage Prices"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 21v-16a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v16l-3 -2l-2 2l-2 -2l-2 2l-2 -2l-3 2" /><path d="M14 8h-2.5a1.5 1.5 0 0 0 0 3h1a1.5 1.5 0 0 1 0 3h-2.5m2 0v1.5m0 -9v1.5" /></svg> Prices</a> <a class="btn btn-outline-teal" href="/ticket/${cell.getRow().getData().tld}" title="Manage Promotions"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 7.2a2.2 2.2 0 0 1 2.2 -2.2h1a2.2 2.2 0 0 0 1.55 -.64l.7 -.7a2.2 2.2 0 0 1 3.12 0l.7 .7c.412 .41 .97 .64 1.55 .64h1a2.2 2.2 0 0 1 2.2 2.2v1c0 .58 .23 1.138 .64 1.55l.7 .7a2.2 2.2 0 0 1 0 3.12l-.7 .7a2.2 2.2 0 0 0 -.64 1.55v1a2.2 2.2 0 0 1 -2.2 2.2h-1a2.2 2.2 0 0 0 -1.55 .64l-.7 .7a2.2 2.2 0 0 1 -3.12 0l-.7 -.7a2.2 2.2 0 0 0 -1.55 -.64h-1a2.2 2.2 0 0 1 -2.2 -2.2v-1a2.2 2.2 0 0 0 -.64 -1.55l-.7 -.7a2.2 2.2 0 0 1 0 -3.12l.7 -.7a2.2 2.2 0 0 0 .64 -1.55v-1" /><path d="M9 12l2 2l4 -4" /></svg> Promotions</a> <a class="btn btn-outline-pink" href="/ticket/${cell.getRow().getData().tld}" title="Manage Premium Names"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" /><path d="M13.867 9.75c-.246 -.48 -.708 -.769 -1.2 -.75h-1.334c-.736 0 -1.333 .67 -1.333 1.5c0 .827 .597 1.499 1.333 1.499h1.334c.736 0 1.333 .671 1.333 1.5c0 .828 -.597 1.499 -1.333 1.499h-1.334c-.492 .019 -.954 -.27 -1.2 -.75" /><path d="M12 7v2" /><path d="M12 15v2" /></svg> Premium Names</a>
`;
return `<a class="btn btn-outline-info" href="/registry/tld/${cell.getRow().getData().tld}" title="Manage Settings"><svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 21v-16a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v16l-3 -2l-2 2l-2 -2l-2 2l-2 -2l-3 2" /><path d="M14 8h-2.5a1.5 1.5 0 0 0 0 3h1a1.5 1.5 0 0 1 0 3h-2.5m2 0v1.5m0 -9v1.5" /></svg> Settings</a>`;
}
table = new Tabulator("#tldTable", {

View file

@ -90,8 +90,8 @@ $app->group('', function ($route) {
$route->get('/registry', SystemController::class .':registry')->setName('registry');
$route->map(['GET', 'POST'], '/registry/tld/create', SystemController::class .':createTld')->setName('createTld');
$route->map(['GET', 'POST'], '/registry/tld/{tld}', SystemController::class . ':viewTld')->setName('viewTld');
$route->get('/registry/tlds', SystemController::class .':manageTlds')->setName('manageTlds');
$route->map(['GET', 'POST'], '/registry/tld/{tld}', SystemController::class . ':manageTld')->setName('manageTld');
$route->get('/registry/tlds', SystemController::class .':listTlds')->setName('listTlds');
$route->map(['GET', 'POST'], '/registry/reserved', SystemController::class .':manageReserved')->setName('manageReserved');
$route->get('/support', SupportController::class .':view')->setName('ticketview');