Add copy structure controller and clipboard functionality
Signed-off-by: Satyam <satyam.gupta756@gmail.com>
This commit is contained in:
parent
e18b197a11
commit
f8e914075b
@ -326,6 +326,10 @@ return [
|
||||
'class' => Database\Structure\ShowCreateController::class,
|
||||
'arguments' => [ResponseRenderer::class, Template::class, DatabaseInterface::class],
|
||||
],
|
||||
Database\Structure\CopyStructureController::class => [
|
||||
'class' => Database\Structure\CopyStructureController::class,
|
||||
'arguments' => [ResponseRenderer::class, DatabaseInterface::class, DbTableExists::class],
|
||||
],
|
||||
Database\StructureController::class => [
|
||||
'class' => Database\StructureController::class,
|
||||
'arguments' => [
|
||||
@ -1131,6 +1135,10 @@ return [
|
||||
DbTableExists::class,
|
||||
],
|
||||
],
|
||||
Table\Structure\CopyStructureController::class => [
|
||||
'class' => Table\Structure\CopyStructureController::class,
|
||||
'arguments' => [ResponseRenderer::class, DatabaseInterface::class, DbTableExists::class],
|
||||
],
|
||||
Table\Structure\ReservedWordCheckController::class => [
|
||||
'class' => Table\Structure\ReservedWordCheckController::class,
|
||||
'arguments' => [ResponseRenderer::class, Config::class],
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import $ from 'jquery';
|
||||
import * as bootstrap from 'bootstrap';
|
||||
import { AJAX } from '../modules/ajax.ts';
|
||||
import { getForeignKeyCheckboxLoader, loadForeignKeyCheckbox } from '../modules/functions.ts';
|
||||
import { copyToClipboard, displayCopyNotification, getForeignKeyCheckboxLoader, loadForeignKeyCheckbox } from '../modules/functions.ts';
|
||||
import { Navigation } from '../modules/navigation.ts';
|
||||
import { CommonParams } from '../modules/common.ts';
|
||||
import { ajaxRemoveMessage, ajaxShowMessage } from '../modules/ajax-message.ts';
|
||||
@ -33,6 +33,7 @@ AJAX.registerTeardown('database/structure.js', function () {
|
||||
$(document).off('click', 'a.truncate_table_anchor.ajax');
|
||||
$(document).off('click', 'a.drop_table_anchor.ajax');
|
||||
$(document).off('click', 'a.favorite_table_anchor.ajax');
|
||||
$(document).off('click', '#copyStructureBtn');
|
||||
$('a.real_row_count').off('click');
|
||||
$('a.row_count_sum').off('click');
|
||||
$('select[name=submit_mult]').off('change');
|
||||
@ -323,4 +324,40 @@ AJAX.registerOnload('database/structure.js', function () {
|
||||
event.preventDefault();
|
||||
fetchRealRowCount($(this));
|
||||
});
|
||||
|
||||
function copyStructureSql (sql: string): void {
|
||||
if (typeof navigator.clipboard !== 'undefined' && typeof navigator.clipboard.writeText === 'function') {
|
||||
navigator.clipboard.writeText(sql).then(() => {
|
||||
displayCopyNotification(true);
|
||||
}).catch(() => {
|
||||
displayCopyNotification(copyToClipboard(sql, '<textarea>'));
|
||||
});
|
||||
} else {
|
||||
displayCopyNotification(copyToClipboard(sql, '<textarea>'));
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on('click', '#copyStructureBtn', function (event) {
|
||||
event.preventDefault();
|
||||
const argsep = CommonParams.get('arg_separator');
|
||||
const db = CommonParams.get('db');
|
||||
const data =
|
||||
'ajax_request=true' + argsep +
|
||||
'ajax_page_request=true' + argsep +
|
||||
'token=' + encodeURIComponent(CommonParams.get('token')) + argsep +
|
||||
'db=' + encodeURIComponent(db);
|
||||
const $msg = ajaxShowMessage(window.Messages.strProcessingRequest);
|
||||
$.post('index.php?route=/database/structure/copy-structure', data, function (response) {
|
||||
ajaxRemoveMessage($msg);
|
||||
if (typeof response !== 'undefined' && response.success === true && typeof response.sql === 'string') {
|
||||
copyStructureSql(response.sql);
|
||||
} else {
|
||||
const err = typeof response !== 'undefined' && typeof response.error === 'string' ? response.error : '';
|
||||
ajaxShowMessage(window.Messages.strErrorProcessingRequest + ' : ' + err, false);
|
||||
}
|
||||
}, 'json').fail(function () {
|
||||
ajaxRemoveMessage($msg);
|
||||
ajaxShowMessage(window.Messages.strErrorProcessingRequest, false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import $ from 'jquery';
|
||||
import { AJAX } from '../modules/ajax.ts';
|
||||
import { checkReservedWordColumns, checkTableEditForm, prepareForAjaxRequest } from '../modules/functions.ts';
|
||||
import { checkReservedWordColumns, checkTableEditForm, copyToClipboard, displayCopyNotification, prepareForAjaxRequest } from '../modules/functions.ts';
|
||||
import { Navigation } from '../modules/navigation.ts';
|
||||
import { CommonParams } from '../modules/common.ts';
|
||||
import highlightSql from '../modules/sql-highlight.ts';
|
||||
@ -60,6 +60,7 @@ AJAX.registerTeardown('table/structure.js', function () {
|
||||
$('body').off('click', '#fieldsForm button.mult_submit');
|
||||
$(document).off('click', 'a[id^=partition_action].ajax');
|
||||
$(document).off('click', '#remove_partitioning.ajax');
|
||||
$(document).off('click', '#copyTableStructureBtn');
|
||||
});
|
||||
|
||||
AJAX.registerOnload('table/structure.js', function () {
|
||||
@ -486,4 +487,42 @@ AJAX.registerOnload('table/structure.js', function () {
|
||||
$(document).on('change', 'select[name=after_field]', function () {
|
||||
checkFirst();
|
||||
});
|
||||
|
||||
function copyTableStructureSql (sql: string): void {
|
||||
if (typeof navigator.clipboard !== 'undefined' && typeof navigator.clipboard.writeText === 'function') {
|
||||
navigator.clipboard.writeText(sql).then(() => {
|
||||
displayCopyNotification(true);
|
||||
}).catch(() => {
|
||||
displayCopyNotification(copyToClipboard(sql, '<textarea>'));
|
||||
});
|
||||
} else {
|
||||
displayCopyNotification(copyToClipboard(sql, '<textarea>'));
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on('click', '#copyTableStructureBtn', function (event) {
|
||||
event.preventDefault();
|
||||
const argsep = CommonParams.get('arg_separator');
|
||||
const db = CommonParams.get('db');
|
||||
const table = CommonParams.get('table');
|
||||
const data =
|
||||
'ajax_request=true' + argsep +
|
||||
'ajax_page_request=true' + argsep +
|
||||
'token=' + encodeURIComponent(CommonParams.get('token')) + argsep +
|
||||
'db=' + encodeURIComponent(db) + argsep +
|
||||
'table=' + encodeURIComponent(table);
|
||||
const $msg = ajaxShowMessage(window.Messages.strProcessingRequest);
|
||||
$.post('index.php?route=/table/structure/copy-structure', data, function (response) {
|
||||
ajaxRemoveMessage($msg);
|
||||
if (typeof response !== 'undefined' && response.success === true && typeof response.sql === 'string') {
|
||||
copyTableStructureSql(response.sql);
|
||||
} else {
|
||||
const err = typeof response !== 'undefined' && typeof response.error === 'string' ? response.error : '';
|
||||
ajaxShowMessage(window.Messages.strErrorProcessingRequest + ' : ' + err, false);
|
||||
}
|
||||
}, 'json').fail(function () {
|
||||
ajaxRemoveMessage($msg);
|
||||
ajaxShowMessage(window.Messages.strErrorProcessingRequest, false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -11,6 +11,9 @@
|
||||
<hr>
|
||||
<p class="d-print-none">
|
||||
<button type="button" class="btn btn-link p-0 jsPrintButton">{{ get_icon('b_print', t('Print'), true) }}</button>
|
||||
<button type="button" id="copyStructureBtn" class="btn btn-link p-0">
|
||||
{{ get_icon('b_export', t('Copy Structure'), true) }}
|
||||
</button>
|
||||
<a href="{{ url('/database/data-dictionary', {'db': database, 'goto': url('/database/structure')}) }}">
|
||||
{{ get_icon('b_tblanalyse', t('Data dictionary'), true) }}
|
||||
</a>
|
||||
|
||||
@ -624,5 +624,12 @@
|
||||
{% if show_stats %}
|
||||
{{ table_stats|raw }}
|
||||
{% endif %}
|
||||
{% if not db_is_system_schema %}
|
||||
<p class="d-print-none mt-2">
|
||||
<button type="button" id="copyTableStructureBtn" class="btn btn-link p-0">
|
||||
{{ get_icon('b_export', t('Copy Table Structure'), true) }}
|
||||
</button>
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="clearfloat"></div>
|
||||
{% endblock %}
|
||||
|
||||
70
src/Controllers/Table/Structure/CopyStructureController.php
Normal file
70
src/Controllers/Table/Structure/CopyStructureController.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Controllers\Table\Structure;
|
||||
|
||||
use PhpMyAdmin\Controllers\InvocableController;
|
||||
use PhpMyAdmin\Current;
|
||||
use PhpMyAdmin\Dbal\DatabaseInterface;
|
||||
use PhpMyAdmin\DbTableExists;
|
||||
use PhpMyAdmin\Http\Response;
|
||||
use PhpMyAdmin\Http\ServerRequest;
|
||||
use PhpMyAdmin\Identifiers\DatabaseName;
|
||||
use PhpMyAdmin\Identifiers\TableName;
|
||||
use PhpMyAdmin\Message;
|
||||
use PhpMyAdmin\ResponseRenderer;
|
||||
use PhpMyAdmin\Routing\Route;
|
||||
|
||||
use function __;
|
||||
|
||||
#[Route('/table/structure/copy-structure', ['POST'])]
|
||||
final readonly class CopyStructureController implements InvocableController
|
||||
{
|
||||
public function __construct(
|
||||
private ResponseRenderer $response,
|
||||
private DatabaseInterface $dbi,
|
||||
private DbTableExists $dbTableExists,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequest $request): Response
|
||||
{
|
||||
if (Current::$database === '') {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', Message::error(__('No databases selected.')));
|
||||
|
||||
return $this->response->response();
|
||||
}
|
||||
|
||||
if (Current::$table === '') {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', Message::error(__('No table selected.')));
|
||||
|
||||
return $this->response->response();
|
||||
}
|
||||
|
||||
$this->dbi->selectDb(Current::$database);
|
||||
|
||||
$databaseName = DatabaseName::tryFrom($request->getParam('db'));
|
||||
if ($databaseName === null || ! $this->dbTableExists->selectDatabase($databaseName)) {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', Message::error(__('No databases selected.')));
|
||||
|
||||
return $this->response->response();
|
||||
}
|
||||
|
||||
$tableName = TableName::tryFrom($request->getParam('table'));
|
||||
if ($tableName === null || ! $this->dbTableExists->hasTable($databaseName, $tableName)) {
|
||||
$this->response->setRequestStatus(false);
|
||||
$this->response->addJSON('message', Message::error(__('No table selected.')));
|
||||
|
||||
return $this->response->response();
|
||||
}
|
||||
|
||||
$object = $this->dbi->getTable(Current::$database, Current::$table);
|
||||
$this->response->addJSON('sql', $object->showCreate());
|
||||
|
||||
return $this->response->response();
|
||||
}
|
||||
}
|
||||
@ -239,6 +239,7 @@ final class RoutesTest extends TestCase
|
||||
'/database/structure/central-columns/remove' => CentralColumns\RemoveController::class,
|
||||
'/database/structure/change-prefix-form' => Database\Structure\ChangePrefixFormController::class,
|
||||
'/database/structure/copy-form' => Database\Structure\CopyFormController::class,
|
||||
'/database/structure/copy-structure' => Database\Structure\CopyStructureController::class,
|
||||
'/database/structure/copy-table' => Database\Structure\CopyTableController::class,
|
||||
'/database/structure/copy-table-with-prefix' => Database\Structure\CopyTableWithPrefixController::class,
|
||||
'/database/structure/drop-form' => Database\Structure\DropFormController::class,
|
||||
@ -357,6 +358,7 @@ final class RoutesTest extends TestCase
|
||||
'/table/structure/central-columns-add' => Table\Structure\CentralColumnsAddController::class,
|
||||
'/table/structure/central-columns-remove' => Table\Structure\CentralColumnsRemoveController::class,
|
||||
'/table/structure/change' => Table\Structure\ChangeController::class,
|
||||
'/table/structure/copy-structure' => Table\Structure\CopyStructureController::class,
|
||||
'/table/structure/drop' => Table\DropColumnController::class,
|
||||
'/table/structure/drop-confirm' => Table\DropColumnConfirmationController::class,
|
||||
'/table/structure/fulltext' => Table\Structure\FulltextController::class,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user