1
0
mirror of https://github.com/flextype/flextype.git synced 2025-08-24 13:52:56 +02:00

feat(admin-plugin): add UI for Delivery Regsitry API

This commit is contained in:
Awilum
2020-02-21 21:24:43 +03:00
parent 62aadb1874
commit 136b6c2268
9 changed files with 484 additions and 1 deletions

View File

@@ -30,7 +30,7 @@ class ApiDeliveryController extends Controller
'plugins/admin/templates/system/api/delivery/index.html',
[
'menu_item' => 'api',
'api_list' => ['entries' => 'Entries', 'images' => 'Images'],
'api_list' => ['entries' => 'Entries', 'images' => 'Images', 'registry' => 'Registry'],
'links' => [
'api' => [
'link' => $this->router->pathFor('admin.api.index'),

View File

@@ -0,0 +1,266 @@
<?php
declare(strict_types=1);
namespace Flextype;
use Flextype\Component\Filesystem\Filesystem;
use Flextype\Component\Session\Session;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Ramsey\Uuid\Uuid;
use function bin2hex;
use function date;
use function Flextype\Component\I18n\__;
use function random_bytes;
use function time;
class ApiDeliveryRegistryController extends Controller
{
/**
* Delivery Registry Index page
*
* @param Request $request PSR7 request
* @param Response $response PSR7 response
*/
public function index(Request $request, Response $response) : Response
{
$tokens = [];
$tokens_list = Filesystem::listContents(PATH['tokens'] . '/delivery/registry/');
if (count($tokens_list) > 0) {
foreach ($tokens_list as $token) {
if ($token['type'] == 'dir' && Filesystem::has(PATH['tokens'] . '/delivery/registry/' . $token['dirname'] . '/token.yaml')) {
$tokens[] = $token;
}
}
}
return $this->view->render(
$response,
'plugins/admin/templates/system/api/delivery/registry/index.html',
[
'menu_item' => 'api',
'tokens' => $tokens,
'links' => [
'api' => [
'link' => $this->router->pathFor('admin.api.index'),
'title' => __('admin_api'),
],
'api_delivery' => [
'link' => $this->router->pathFor('admin.api_delivery.index'),
'title' => __('admin_delivery')
],
'api_delivery_registry' => [
'link' => $this->router->pathFor('admin.api_delivery_registry.index'),
'title' => __('admin_registry'),
'active' => true
],
],
'buttons' => [
'api_delivery_registry_add' => [
'link' => $this->router->pathFor('admin.api_delivery_registry.add'),
'title' => __('admin_create_new_token')
],
],
]
);
}
/**
* Add token page
*
* @param Request $request PSR7 request
* @param Response $response PSR7 response
*/
public function add(Request $request, Response $response) : Response
{
return $this->view->render(
$response,
'plugins/admin/templates/system/api/delivery/registry/add.html',
[
'menu_item' => 'api',
'links' => [
'api' => [
'link' => $this->router->pathFor('admin.api.index'),
'title' => __('admin_api'),
],
'api_delivery' => [
'link' => $this->router->pathFor('admin.api_delivery.index'),
'title' => __('admin_delivery')
],
'api_delivery_registry' => [
'link' => $this->router->pathFor('admin.api_delivery_registry.index'),
'title' => __('admin_registry')
],
'api_delivery_registry_add' => [
'link' => $this->router->pathFor('admin.api_delivery_registry.add'),
'title' => __('admin_create_new_token'),
'active' => true
],
],
]
);
}
/**
* Add new token - process
*
* @param Request $request PSR7 request
* @param Response $response PSR7 response
*/
public function addProcess(Request $request, Response $response) : Response
{
// Get POST data
$post_data = $request->getParsedBody();
// Generate API token
$api_token = bin2hex(random_bytes(16));
$api_token_dir_path = PATH['tokens'] . '/delivery/registry/' . $api_token;
$api_token_file_path = $api_token_dir_path . '/token.yaml';
if (! Filesystem::has($api_token_file_path)) {
Filesystem::createDir($api_token_dir_path);
// Generate UUID
$uuid = Uuid::uuid4()->toString();
// Get time
$time = date($this->registry->get('flextype.date_format'), time());
// Create API Token account
if (Filesystem::write(
$api_token_file_path,
$this->parser->encode([
'title' => $post_data['title'],
'icon' => $post_data['icon'],
'limit_calls' => (int) $post_data['limit_calls'],
'calls' => (int) 0,
'state' => $post_data['state'],
'uuid' => $uuid,
'created_by' => Session::get('uuid'),
'created_at' => $time,
'updated_by' => Session::get('uuid'),
'updated_at' => $time,
], 'yaml')
)) {
$this->flash->addMessage('success', __('admin_message_delivery_registry_api_token_created'));
} else {
$this->flash->addMessage('error', __('admin_message_delivery_registry_api_token_was_not_created1'));
}
} else {
$this->flash->addMessage('error', __('admin_message_delivery_registry_api_token_was_not_created2'));
}
if (isset($post_data['create-and-edit'])) {
return $response->withRedirect($this->router->pathFor('admin.api_delivery_registry.edit') . '?token=' . $api_token);
} else {
return $response->withRedirect($this->router->pathFor('admin.api_delivery_registry.index'));
}
}
/**
* Edit token page
*
* @param Request $request PSR7 request
* @param Response $response PSR7 response
*/
public function edit(Request $request, Response $response) : Response
{
$token = $request->getQueryParams()['token'];
$token_data = $this->parser->decode(Filesystem::read(PATH['tokens'] . '/delivery/registry/' . $token . '/token.yaml'), 'yaml');
return $this->view->render(
$response,
'plugins/admin/templates/system/api/delivery/registry/edit.html',
[
'menu_item' => 'api',
'token' => $token,
'token_data' => $token_data,
'links' => [
'api' => [
'link' => $this->router->pathFor('admin.api.index'),
'title' => __('admin_api')
],
'api_tokens' => [
'link' => $this->router->pathFor('admin.api_delivery.index'),
'title' => __('admin_delivery')
],
'api_delivery_registry' => [
'link' => $this->router->pathFor('admin.api_delivery_registry.index'),
'title' => __('admin_registry')
],
'api_tokens_edit' => [
'link' => $this->router->pathFor('admin.api_delivery_registry.edit'),
'title' => __('admin_edit_delivery_token'),
'active' => true
],
]
]
);
}
/**
* Edit token - process
*
* @param Request $request PSR7 request
* @param Response $response PSR7 response
*/
public function editProcess(Request $request, Response $response) : Response
{
// Get POST data
$post_data = $request->getParsedBody();
$api_token_dir_path = PATH['tokens'] . '/delivery/registry/' . $post_data['token'];
$api_token_file_path = $api_token_dir_path . '/' . 'token.yaml';
// Update API Token File
if (Filesystem::has($api_token_file_path)) {
if (Filesystem::write(
$api_token_file_path,
$this->parser->encode([
'title' => $post_data['title'],
'icon' => $post_data['icon'],
'limit_calls' => (int) $post_data['limit_calls'],
'calls' => (int) $post_data['calls'],
'state' => $post_data['state'],
'uuid' => $post_data['uuid'],
'created_by' => $post_data['created_by'],
'created_at' => $post_data['created_at'],
'updated_by' => Session::get('uuid'),
'updated_at' => date($this->registry->get('flextype.date_format'), time()),
], 'yaml')
)) {
$this->flash->addMessage('success', __('admin_message_delivery_registry_api_token_updated'));
}
} else {
$this->flash->addMessage('error', __('admin_message_delivery_registry_api_token_was_not_updated'));
}
return $response->withRedirect($this->router->pathFor('admin.api_delivery_registry.index'));
}
/**
* Delete token - process
*
* @param Request $request PSR7 request
* @param Response $response PSR7 response
*/
public function deleteProcess(Request $request, Response $response) : Response
{
// Get POST data
$post_data = $request->getParsedBody();
$api_token_dir_path = PATH['tokens'] . '/delivery/registry/' . $post_data['token'];
if (Filesystem::deleteDir($api_token_dir_path)) {
$this->flash->addMessage('success', __('admin_message_delivery_registry_api_token_deleted'));
} else {
$this->flash->addMessage('error', __('admin_message_delivery_registry_api_token_was_not_deleted'));
}
return $response->withRedirect($this->router->pathFor('admin.api_delivery_registry.index'));
}
}

View File

@@ -88,3 +88,7 @@ $flextype['ApiDeliveryEntriesController'] = static function ($container) {
$flextype['ApiDeliveryImagesController'] = static function ($container) {
return new ApiDeliveryImagesController($container);
};
$flextype['ApiDeliveryRegistryController'] = static function ($container) {
return new ApiDeliveryRegistryController($container);
};

View File

@@ -351,6 +351,14 @@ admin_message_delivery_entries_api_token_deleted: "Delivery token for entries de
admin_message_delivery_entries_api_token_was_not_deleted: "Delivery token for entries was not deleted."
admin_confirmation_required_for_delivery_entries_token_delete: "Are you sure you want to delete this delivery token for entries?"
admin_you_have_not_created_any_delivery_images_api_tokens_yet: "You haven't created any Delivery Images tokens yet!"
admin_you_have_not_created_any_delivery_registry_api_tokens_yet: "You haven't created any Delivery Registry tokens yet!"
admin_message_delivery_registry_api_token_updated: "Delivery token for registry updated."
admin_message_delivery_registry_api_token_was_not_updated: "Delivery token for registry was not updated."
admin_message_delivery_registry_api_token_created: "Delivery token for registry created."
admin_message_delivery_registry_api_token_was_not_created: "Delivery token for registry was not created."
admin_message_delivery_registry_api_token_deleted: "Delivery token for registry deleted."
admin_message_delivery_registry_api_token_was_not_deleted: "Delivery token for registry was not deleted."
admin_confirmation_required_for_delivery_registry_token_delete: "Are you sure you want to delete this delivery token for registry?"
admin_message_delivery_images_api_token_updated: "Delivery token for images updated."
admin_message_delivery_images_api_token_was_not_updated: "Delivery token for images was not updated."
admin_message_delivery_images_api_token_created: "Delivery token for images created."

View File

@@ -116,5 +116,11 @@ $app->group('/' . $admin_route, function () use ($app) : void {
$app->post('/api/delivery/images/edit', 'ApiDeliveryImagesController:editProcess')->setName('admin.api_delivery_images.editProcess');
$app->post('/api/delivery/images/delete', 'ApiDeliveryImagesController:deleteProcess')->setName('admin.api_delivery_images.deleteProcess');
$app->get('/api/delivery/registry', 'ApiDeliveryRegistryController:index')->setName('admin.api_delivery_registry.index');
$app->get('/api/delivery/registry/add', 'ApiDeliveryRegistryController:add')->setName('admin.api_delivery_registry.add');
$app->post('/api/delivery/registry/add', 'ApiDeliveryRegistryController:addProcess')->setName('admin.api_delivery_registry.addProcess');
$app->get('/api/delivery/registry/edit', 'ApiDeliveryRegistryController:edit')->setName('admin.api_delivery_registry.edit');
$app->post('/api/delivery/registry/edit', 'ApiDeliveryRegistryController:editProcess')->setName('admin.api_delivery_registry.editProcess');
$app->post('/api/delivery/registry/delete', 'ApiDeliveryRegistryController:deleteProcess')->setName('admin.api_delivery_registry.deleteProcess');
})->add(new AuthMiddleware($flextype));

View File

@@ -21,6 +21,9 @@
{% if key == 'images' %}
<i class="icon">{{ icon('far fa-images') }}</i>
{% endif %}
{% if key == 'registry' %}
<i class="icon">{{ icon('fas fa-archive') }}</i>
{% endif %}
</td>
<td>
<a href="{{ path_for('admin.api.index') }}/delivery/{{ key }}">{{ api }}</a>

View File

@@ -0,0 +1,54 @@
{% extends "plugins/admin/templates/partials/base.html" %}
{% block content %}
<form method="post" id="form" data-parsley-validate="data-parsley-validate">
{{ csrf() }}
<div class="flex row">
<div class="col w-full lg:w-4/12">
<div class="form-group">
<label for="title" class="form-control-title">{{ tr('admin_title') }}</label>
<input type="text" id="title" name="title" value="" class="form-control" required="required" data-parsley-minlength="1" data-parsley-error-message="{{ tr('admin_error_title_empty_input') }}" data-parsley-required="true">
<small>{{ tr('admin_help_text_for_tokens_label') }}</small>
</div>
<div class="form-group">
<label for="title" class="form-control-title">{{ tr('admin_api_calls_limit') }}</label>
<input
type="text"
id="limit"
name="limit_calls"
value="0"
class="form-control"
required="required"
data-parsley-required="true"
data-parsley-minlength="1"
data-parsley-type="integer"
data-parsley-error-message="{{ tr('admin_error_api_calls_empty_input') }}">
<small>{{ tr('admin_help_text_for_api_calls_limit_label') }}</small>
</div>
<div class="form-group">
<label for="icon" class="form-control-title">{{ tr('admin_icon') }}</label>
<input type="text" id="fieldsetIcon" name="icon" value="fas fa-database" class="form-control" required="required" data-parsley-required="true" data-parsley-minlength="1" data-parsley-error-message="{{ tr('admin_error_icon_empty_input') }}">
<small>{{ tr('admin_help_text_for_api_token_icon', {':link': '<a href="https://fontawesome.com/icons?d=gallery&m=free" target="_blank">fontawesome</a>'})|raw }}</small>
</div>
<div class="form-group">
<label for="type" class="form-control-title">{{ tr('admin_state') }}</label>
<select class="js-select form-control" name="state">
<option value="enabled" selected="selected">{{ tr('admin_enabled') }}</option>
<option value="disabled">{{ tr('admin_disabled') }}</option>
</select>
</div>
<div class="button-group">
<div class="button-dropdown">
<input type="submit" id="create" name="create" value="{{ tr('admin_create') }}" class="button">
<a href="javascript:;" class="button js-dropdown-btn" data-dropdown="dropdown-list-create-new-token">
<i class="icon icon--white">{{ icon('fas fa-sort-down') }}</i>
</a>
<div id="dropdown-list-create-new-token" class="dropdown">
<input type="submit" id="create-and-edit" name="create-and-edit" value="{{ tr('admin_create_and_edit') }}" class="dropdown__item">
</div>
</div>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,51 @@
{% extends "plugins/admin/templates/partials/base.html" %}
{% block content %}
<form method="post" id="form">
{{ csrf() }}
<input type="hidden" name="token" value="{{ token }}">
<input type="hidden" name="created_by" value="{{ token_data.created_by }}">
<input type="hidden" name="created_at" value="{{ token_data.created_at }}">
<input type="hidden" name="uuid" value="{{ token_data.uuid }}">
<input type="hidden" name="calls" value="{{ token_data.calls }}">
<div class="flex row">
<div class="col w-full lg:w-4/12">
<div class="form-group">
<label for="title" class="form-control-title">{{ tr('admin_title') }}</label>
<input type="text" id="title" name="title" value="{{ token_data.title }}" class="form-control" required="required" data-parsley-minlength="1" data-parsley-error-message="{{ tr('admin_error_title_empty_input') }}" data-parsley-required="true">
<small>{{ tr('admin_help_text_for_tokens_label') }}</small>
</div>
<div class="form-group">
<label for="title" class="form-control-title">{{ tr('admin_api_calls_limit') }}</label>
<input
type="text"
id="limit"
name="limit_calls"
value="{{ token_data.limit_calls }}"
class="form-control"
required="required"
data-parsley-required="true"
data-parsley-minlength="1"
data-parsley-type="integer"
data-parsley-error-message="{{ tr('admin_error_api_calls_empty_input') }}">
<small>{{ tr('admin_help_text_for_api_calls_limit_label') }}</small>
</div>
<div class="form-group">
<label for="icon" class="form-control-title">{{ tr('admin_icon') }}</label>
<input type="text" id="fieldsetIcon" name="icon" value="{{ token_data.icon }}" class="form-control" required="required" data-parsley-required="true" data-parsley-minlength="1" data-parsley-error-message="{{ tr('admin_error_icon_empty_input') }}">
<small>{{ tr('admin_help_text_for_api_token_icon', {':link': '<a href="https://fontawesome.com/icons?d=gallery&m=free" target="_blank">fontawesome</a>'})|raw }}</small>
</div>
<div class="form-group">
<label for="type" class="form-control-title">{{ tr('admin_state') }}</label>
<select class="form-control js-select" name="state">
<option value="enabled" {% if token_data.state == 'enabled' %} selected="selected" {% endif %}>{{ tr('admin_enabled') }}</option>
<option value="disabled" {% if token_data.state == 'disabled' %} selected="selected" {% endif %} ">{{ tr('admin_disabled') }}</option>
</select>
</div>
<div class="button-group">
<input type="submit" id="save" name="save" value="{{ tr('admin_save') }}" class="button">
</div>
</div>
</div>
</form>
{% endblock %}

View File

@@ -0,0 +1,91 @@
{% extends "plugins/admin/templates/partials/base.html" %}
{% block content %}
{% if (tokens | length > 0) %}
<table class="table">
<thead>
<tr>
<th></th>
<th>
{{ tr('admin_title') }}
</th>
<th>
{{ tr('admin_token') }}
</th>
<th>
{{ tr('admin_calls') }}
</th>
</tr>
</thead>
<tbody>
{% for key, token in tokens %}
{% set token_file_path = PATH_TOKENS ~ '/delivery/registry/' ~ token.dirname ~ '/' ~ 'token.yaml' %}
{% if filesystem_has(token_file_path) %}
{% set token_data = parser_decode(filesystem_read(token_file_path), 'yaml') %}
{% endif %}
<tr>
<td class="w-1 text-center {% if token_data.state == 'disabled' %}opacity-50{% endif %}">
<i class="icon">{{ icon(token_data.icon) }}</i>
</td>
<td class="{% if token_data.state == 'disabled' %}opacity-50{% endif %}">
<a href="{{ path_for('admin.api_delivery_registry.edit') }}?token={{ token.dirname }}">{{ token_data.title }}</a>
</td>
<td class="{% if token_data.state == 'disabled' %}opacity-50{% endif %}">{{ token.dirname }}</td>
<td class="{% if token_data.state == 'disabled' %}opacity-50{% endif %}">{{ token_data.calls }}
/
{% if (token_data.limit_calls > 0) %}{{ token_data.limit_calls }}
{% else %}&infin;{% endif %}
</td>
<td class="text-right">
<button type="button" class="js-dropdown-btn" data-dropdown="dropdown-delivery-registry-{{ token.dirname }}">
<i class="icon">{{ icon('fas fa-ellipsis-h') }}</i>
</button>
<div id="dropdown-delivery-registry-{{ token.dirname }}" class="dropdown">
<a class="dropdown__item" href="{{ path_for('admin.api_delivery_registry.edit') }}?token={{ token.dirname }}">
<i class="icon icon--white mr-3">{{ icon('fas fa-edit') }}</i>
{{ tr('admin_edit') }}
</a>
<div class="dropdown__divider"></div>
<a class="dropdown__item" href="javascript:;" onclick="event.preventDefault(); deleteDeliveryRegistryToken('{{ token.dirname }}', {{ loop.index0 }});">
<i class="icon icon--white mr-3">{{ icon('fas fa-trash-alt') }}</i>
{{ tr('admin_delete') }}
</a>
<form id="delete-api-token-id-{{ token.dirname }}" action="{{ path_for('admin.api_delivery_registry.deleteProcess') }}" method="POST" style="display: none;">
{{ csrf() }}
<input type="hidden" name="token" value="{{ token.dirname }}">
</form>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="text-center flex justify-center items-center h-full">
<div>
<i class="icon icon--4xl">{{ icon('fas fa-archive') }}</i>
<i class="icon icon--4xl mr-3 ml-3">{{ icon('fas angle-right') }}</i>
<i class="icon icon--4xl">{{ icon('fas fa-truck') }}</i>
<h3 class="text-2xl pt-5 pb-8">{{ tr('admin_you_have_not_created_any_delivery_registry_api_tokens_yet') }}</h3>
<a href="{{ path_for('admin.api_delivery_registry.add') }}" class="button">{{ tr('admin_create_new_token') }}</a>
</div>
</div>
{% endif %}
{% endblock %}
{% block tail %}
<script>
function deleteDeliveryRegistryToken(id, row_num) {
if (dropdown[row_num]) {
dropdown[row_num].hide();
}
Swal.fire(
{title: "{{ tr('admin_confirmation_required') }}", text: "{{ tr('admin_confirmation_required_for_delivery_registry_token_delete') }}", showCancelButton: true, confirmButtonText: "{{ tr('admin_yes_iam_sure')|raw }}", cancelButtonText: "{{ tr('admin_cancel') }}"}
).then((result) => {
if (result.value) {
document.getElementById('delete-api-token-id-' + id).submit();
}
});
}
</script>
{% endblock %}