Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suche in QuickNavigation integriert #8

Merged
merged 3 commits into from
May 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
# Wildcard - Ersetzungen von Sprach-Platzhaltern in REDAXO neu gedacht
# 🎴 Wildcard - Ersetzungen von Sprach-Platzhaltern in REDAXO neu gedacht

Wildcard lässt dich Platzhalter nutzen, die du in deinem Addon oder Theme definierst. Redakteure können dadurch deine Sprachübersetzungen nutzen oder mit eigenen überschreiben. Die Änderungen bleiben dann auch bei einem Update deines Addons erhalten.

## Geplante Features
## Features

* Ersetzung von Platzhaltern in jeder Sprache
* Einfache Verwaltung durch YForm: Exportieren und importieren von Sprachdateien
* Automatische Erkennung von Sprachdateien in Addons (Verzeichnis: `package/wildcard/de_de.lang`)
* Synchronisation von Wildcard-Dateien von Addons in das Projekt
* Einfaches Kopieren und Einfügen von Platzhaltern

## Geplante Features

* Automatische Erkennung von Sprachdateien in Addons (Verzeichnis: `src/addons/<addon>/wildcard/translate.json`)
* Kombination mit YForm_Inline-Addon für eine einfachere Bearbeitung
* Unterstützung von Cloud-Übersetzungstools

## Voraussetzungen

Expand Down
85 changes: 85 additions & 0 deletions assets/js/backend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
function data_copy(event) {
// Holt das aktuelle Element, auf das geklickt wurde
var element = event.currentTarget;
// Fügt die Klasse "copied" zum aktuellen Element hinzu
element.classList.add('copied');
// Sucht das icon-Element im aktuellen Element
var iconElement = element.querySelector('i');
// Entfernt die Klasse "fa-clone" vom i-Element
iconElement.classList.remove('fa-clone');
// Fügt die Klasse "fa-check" zum i-Element hinzu
iconElement.classList.add('fa-check');
// Kopiert den Wert des data-wildcard-copy Attributs in die Zwischenablage
navigator.clipboard.writeText(element.getAttribute('data-wildcard-copy'));
};

$(document).on("rex:ready", function(wildcard, container) {

// Fügt den Click-Event-Listener zu allen div-Elementen mit dem data-wildcard-copy Attribut hinzu
document.querySelectorAll('div[data-wildcard-copy]').forEach(function(el) {
el.addEventListener('click', data_copy)
})

// Warte auf QuickNavigation - Event an das Formular erst nach 2 Sekunden
setTimeout(function() {

// Fügt den Submit-Event-Listener zum Formular mit der ID "wildcard_search" hinzu
$('#wildcard_search').on('submit', function(e) {
// Verhindert das Absenden des Formulars
e.preventDefault();

// Sendet eine AJAX-Anfrage
$.ajax({
url: '/', // URL, an die die Anfrage gesendet wird
type: 'GET', // Methode der Anfrage
data: {
"rex-api-call": 'wildcard_search', // Daten, die an den Server gesendet werden
"q": $('input[name="q"]').val() // Wert des Eingabefelds
},
success: function(response) {
// Erstellt ein leeres table-Element und fügt Klassen hinzu
var table = $('<table></table>');
table.addClass('table table-striped table-hover');
// Erstellt ein leeres tbody-Element
var tbody = $('<tbody></tbody>');

// Durchläuft jedes Element im Antwortobjekt
$.each(response, function(key, value) {
// Erstellt ein neues tr-Element und fügt das gewünschte HTML hinzu
var tr = $('<tr></tr>');
var th = $('<th></th>');
var div = $('<div></div>').attr('data-wildcard-copy', key).attr('role', 'button');
var i = $('<i></i>').addClass('fa fa-clone').attr('aria-hidden', 'true');
var code = $('<code></code>').text(key);
div.append(i);
div.append(code);
th.append(div);
var td = $('<td></td>').text("⫸ " + value['de_DE']);
tr.append(th);
tr.append(td);

// Fügt das tr-Element zum tbody-Element hinzu
tbody.append(tr);
// Fügt das tbody-Element zum table-Element hinzu
table.append(tbody);
});

// Fügt das table-Element in das div mit der ID "wildcardSearchResults" ein
$('#wildcardSearchResults').html(table);

// Fügt den Click-Event-Listener zu allen neuen div-Elementen mit dem data-wildcard-copy Attribut hinzu
document.querySelectorAll('div[data-wildcard-copy]').forEach(function(el) {
el.addEventListener('click', data_copy)
})

},
error: function() {
// Zeigt eine Fehlermeldung an, wenn ein Fehler auftritt
$('#wildcardSearchResults').html('Ein Fehler ist aufgetreten.');
}
});
});

}, 2000);

});
44 changes: 44 additions & 0 deletions boot.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

namespace Alexplusde\Wildcard;

use FriendsOfRedaxo\QuickNavigation\Button\ButtonRegistry;
use rex;
use rex_addon;
use rex_config;
use rex_extension;
use rex_package;
use rex_view;
use rex_yform_manager_dataset;

if (rex_addon::get('yform')->isAvailable() && !rex::isSafeMode()) {
Expand All @@ -14,6 +18,11 @@
);
}

if (rex::isBackend() && rex::isDebugMode() && rex_addon::get('developer') && rex_addon::get('developer')->isAvailable()) {
FragmentScanner::scan('sh_neues');
Sync::fileToDb();
}

require_once __DIR__ . '/functions/wildcard.php';

if (rex::isFrontend()) {
Expand All @@ -25,6 +34,41 @@
rex_extension::register('CLANG_DELETED', 'Alexplusde\Wildcard\Wildcard::removeClangColumn');
}

/* Darstellung im Backend der Datalist ändern */
if (rex::isBackend()) {
rex_extension::register('YFORM_DATA_LIST', static function ($ep) {
if ('rex_wildcard' == $ep->getParam('table')->getTableName()) {
$list = $ep->getSubject();

$list->setColumnFormat(
'package',
'custom',
static function ($a) {
/* get the icon of the package.yml of the addon */
$packageIcon = rex_package::get($a['list']->getValue('package'))->getProperty('page')['icon'] ?? 'rex-icon-package';
return '<div class="text-nowrap"><i class="rex-icon ' . $packageIcon . '"></i>&nbsp;' . $a['list']->getValue('package') . '</div>';
},
);
$list->setColumnFormat(
'wildcard',
'custom',
static function ($a) {
$value = rex_config::get('wildcard', 'opentag') . $a['list']->getValue('wildcard') . rex_config::get('wildcard', 'closetag');
return '<div class="text-nowrap" data-wildcard-copy="' . $value . '" role="button"> <i class="rex-icon fa-clone"></i> <code> ' . $a['list']->getValue('wildcard') . '</code></div>';
},
);
}
});
}

/* Javascript-Asset laden */
if (rex::isBackend() && rex::getUser()) {
rex_view::addJsFile($this->getAssetsUrl('js/backend.js'));
}

/* Wenn quick_navigation installiert, dann */
ButtonRegistry::registerButton(new QuickNavigationButton(), 5);

if (rex::isDebugMode() && rex_addon::get('developer')->isAvailable()) {
FragmentsScanner::scan();
}
26 changes: 26 additions & 0 deletions fragments/wildcard/backend/WildcardQuicknavigationButton.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

<div class="btn-group dropdown">
<form action="/" method="get" id="wildcard_search">
<input type="hidden" name="rex-api-call" value="wildcard_search">
<button class="btn btn-secondary dropdown-toggle" type="button" id="wildcardSearchQuicknavigationButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="rex-icon fa-language"> </i> <span class="caret"></span>
</button>
<div style="max-width: calc(100vw - 200px); width: 700px" class="quicknavi quicknavi-items list-group dropdown-menu dropdown-menu-right" aria-labelledby="wildcardSearch">
<div style="padding: 10px;">


<div class="input-group">
<input type="search" class="form-control" name="q" placeholder="<?= \rex_i18n::msg('wildcard_quicknavigation_search_placeholder') ?>">
<span class="input-group-btn">
<button class="btn btn-primary" id="wildcardSearchButton"><span class="rex-icon fa-search"></span> <?= \rex_i18n::msg('wildcard_quicknavigation_search_button') ?></button>
</span>
</div>
</form>

<div id="wildcardSearchResults" style="padding-top: 10px;">
</div>
</div>


</div>
</div>
1 change: 0 additions & 1 deletion install.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
$table = $table->ensureColumn(new rex_sql_column('package', 'varchar(191)', false, 'project'));
$table = $table->ensureColumn(new rex_sql_column('wildcard', 'varchar(191)', false, ''));
foreach (rex_clang::getAll() as $clang) {
$table = $table->ensureColumn(new rex_sql_column('text_' . $clang->getId(), 'text', true));
$table = $table->ensureColumn(new rex_sql_column('text_' . rex_string::normalize($clang->getCode()), 'text', true));
}
$table = $table->ensureColumn(new rex_sql_column('createdate', 'datetime'));
Expand Down
13 changes: 9 additions & 4 deletions lang/de_de.lang
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,24 @@ wildcard_docs = Hilfe

# Konfigurationsformulare
wildcard_config = Einstellungen
wildcard_config_starttag_label = Start-Marker
wildcard_config_starttag_notice = z.B. <code>{{ </code>
wildcard_config_endtag_label = End-Marker
wildcard_config_endtag_notice = z.B. <code> }}</code>
wildcard_config_opentag_label = Start-Marker
wildcard_config_opentag_notice = z.B. <code>{{ </code>
wildcard_config_closetag_label = End-Marker
wildcard_config_closetag_notice = z.B. <code> }}</code>

# YForm Tabellen-Übersetzung
wildcard_package = Package (AddOn)
wildcard_wildcard = Platzhalter
wildcard_text_de = DE
wildcard_text_de_DE = de_DE
wildcard_text_en = EN
wildcard_text_en_GB = en_GB
wildcard_text_fr = FR
wildcard_text_es = ES
wildcard_createdate = Erstellt am...
wildcard_createuser = Erstellt von...
wildcard_updatedate = Zuletzt geändert am...
wildcard_updateuser = Zuletzt geändert von...

wildcard_quicknavigation_search_button = Suchen
wildcard_quicknavigation_search_placeholder = Platzhalter oder Text eingeben
15 changes: 15 additions & 0 deletions lib/QuickNavigationButton.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Alexplusde\Wildcard;

use FriendsOfRedaxo\QuickNavigation\Button\ButtonInterface;
use rex_fragment;

class QuickNavigationButton implements ButtonInterface
{
public function get(): string
{
$fragment = new rex_fragment();
return $fragment->parse('wildcard/backend/WildcardQuicknavigationButton.php');
}
}
60 changes: 52 additions & 8 deletions lib/Sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,62 @@

namespace Alexplusde\Wildcard;

use rex_config;
use rex_file;
use rex_path;

use function dirname;

use const DIRECTORY_SEPARATOR;

class Sync
{
/*
* WIP
/* Synchronisiere die Wildcard-Dateien mit der Datenbank. */
private static function getWildcardFiles(?string $packageName = null): array
{
if ($packageName) {
return [rex_path::addon($packageName) . 'wildcard' . DIRECTORY_SEPARATOR . 'translations.json'];
}
return glob(rex_path::src('addons') . DIRECTORY_SEPARATOR . '*' . DIRECTORY_SEPARATOR . 'wildcard' . DIRECTORY_SEPARATOR . 'translations.json');
}

public static function fileToDb()
{
// Hole alle Wildcard-Dateien.
$wildcardFiles = self::getWildcardFiles();

foreach ($wildcardFiles as $wildcardFile) {
// Lese die Datei ein.
$wildcardData = json_decode(rex_file::get($wildcardFile), true);
$packageName = basename(dirname($wildcardFile, 2));

// Trage alle Übersetzungen in die Datenbank ein.
if (!isset($wildcardData['wildcards'])) {
continue;
}

foreach ($wildcardData['wildcards'] as $wildcard => $data) {
if (!$wildcard || !$data) {
continue;
}

public static function sync()
{
// Prüfe, ob die Datei neuer ist als der Zeitstempel in der Datenbank.
if (date(rex_config::get('wildcard', 'syncdatestamp') >= date())) {
$wildcard_dataset = wildcard::findByWildcard($packageName, $wildcard);
if ($wildcard_dataset && ($wildcard_dataset->getUpdatedate() <= $data['timestamp'])) {
// continue;
}
if (!$wildcard_dataset) {
/** @var Wildcard $yform_wildcard */
$wildcard_dataset = Wildcard::create();
$wildcard_dataset->setValue('package', $packageName);
$wildcard_dataset->setValue('wildcard', $wildcard);
$wildcard_dataset->setValue('createuser', '🎴');
}
if (isset($data['de_DE'])) {
dd($data['de_DE']);
$wildcard_dataset->setValue('text_de_DE', $data['de_DE']);
}
$wildcard_dataset->setValue('updatedate', $data['timestamp']);
$wildcard_dataset->save();
}
}
*/
}
}
24 changes: 24 additions & 0 deletions lib/rex_api_call_wildcard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

use Alexplusde\Wildcard\Wildcard;

class rex_api_wildcard_search extends rex_api_function
{
protected $published = true;

public function execute()
{
$search = rex_request('q', 'string', '');
$result = Wildcard::query()->whereRaw(
"`package` LIKE '%" . $search . "%' OR `wildcard` LIKE '%" . $search . "%' OR `text_de_DE` LIKE '%" . $search . "%'",
)->limit(10)->orderBy('package')->orderBy('wildcard')->find(['search' => $search]);
$wildcards = [];
foreach ($result as $item) {
$wildcards[$item->wildcard] = ['de_DE' => $item->text_de_DE];
}
/* Header setzen */
header('Content-Type: application/json');
echo json_encode($wildcards);
exit;
}
}
8 changes: 8 additions & 0 deletions lib/wildcard.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ public static function getCurrentFieldName($field = 'text', $separator = '_')
return $field . $separator . rex_clang::getCurrentId();
}

public static function findByWildcard(string $package, string $wildcard): ?self
{
return self::query()
->where('wildcard', $wildcard)
->where('package', $package)
->findOne();
}

public static function findWildcard(string $wildcard, mixed $clang_code = null)
{
$clang_code ??= rex_clang::getCurrent()->getCode();
Expand Down
6 changes: 3 additions & 3 deletions package.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package: wildcard
version: '0.1.0-dev-2024-05-12'
version: '0.1.0-2024-05-12'
author: 'Alexander Walther'
supportpage: https://github.com/alexplusde/wildcard

Expand Down Expand Up @@ -38,8 +38,8 @@ page:

default_config:
syncdatestamp: ''
open_tag: '{{'
close_tag: '}}'
opentag: '{{'
closetag: '}}'

installer_ignore:
- .git
Expand Down
1 change: 1 addition & 0 deletions pages/docs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?=/** Standard-Methoden, um README.md in REDAXO auszugeben */ rex_view::title(rex_i18n::msg('wildcard_title'));
1 change: 1 addition & 0 deletions pages/index.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<?php

echo rex_view::title(rex_i18n::msg('wildcard_title'));
rex_be_controller::includeCurrentPageSubPath();
Loading
Loading