Skip to content

Commit

Permalink
Add icon editor
Browse files Browse the repository at this point in the history
  • Loading branch information
danon committed Oct 18, 2024
1 parent fca7525 commit e992db8
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 2 deletions.
7 changes: 5 additions & 2 deletions app/Domain/Icon/Icons.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Coyote\Domain\Html;
use Coyote\Domain\StringHtml;
use Illuminate\Support\Facades\Session;

readonly class Icons
{
Expand Down Expand Up @@ -36,7 +37,7 @@ private function iconTag(string $class, string $iconName): Html

private function iconClass(string $iconName): string
{
$icons = $this->fa->icons();
$icons = $this->icons();
if (\array_key_exists($iconName, $icons)) {
return $icons[$iconName];
}
Expand All @@ -45,6 +46,8 @@ private function iconClass(string $iconName): string

public function icons(): array
{
return $this->fa->icons();
$defaultIcons = $this->fa->icons();
$currentIcons = \array_filter(Session::get('icons', []));
return \array_merge($defaultIcons, $currentIcons);
}
}
1 change: 1 addition & 0 deletions app/Http/Controllers/Adm/BaseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ private function buildMenu(Menu $menu): Builder
$menu->add('Bloki statyczne', ['route' => 'adm.blocks'])->prepend($fa('far fa-file-code fa-fw'));
$menu->add('Faktury i płatności', ['route' => 'adm.payments'])->prepend($fa('fa-cart-shopping fa-fw'))->data('permission', 'adm-payment');
$menu->add('Eksperymenty', ['route' => 'adm.experiments'])->prepend($fa('fa-solid fa-flask fa-fw'));
$menu->add('Ikony', ['route' => 'adm.icons'])->prepend($fa('fa-solid fa-icons fa-fw'));
})
->filter(function (Item $item): bool {
if ($item->data('permission')) {
Expand Down
53 changes: 53 additions & 0 deletions app/Http/Controllers/Adm/IconsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
namespace Coyote\Http\Controllers\Adm;

use Coyote\Domain\Icon\FontAwesomePro;
use Illuminate\Database\Connection;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Session;
use Illuminate\View\View;

class IconsController extends BaseController
{
public function __construct()
{
parent::__construct();
$this->breadcrumb->push('Ikony', route('adm.icons'));
}

public function index(FontAwesomePro $icons, Connection $connection): View
{
return $this->view('adm.icons', [
'editorIcons' => $this->editorIcons(\array_filter($icons->icons()), $connection),
]);
}

private function editorIcons(array $icons, Connection $connection): array
{
$record = $connection->table('settings_key_value')->where('key', 'currentIcons')->first();
if ($record) {
$sessionIcons = \json_decode($record->value, true);
} else {
$sessionIcons = [];
}
$editorIcons = [];
foreach ($icons as $iconName => $defaultIcon) {
$editorIcons[$iconName] = [$defaultIcon, $sessionIcons[$iconName] ?? ''];
}
return $editorIcons;
}

public function save(Connection $connection): RedirectResponse
{
$currentIcons = $this->request->get('icons');
Session::put('icons', $currentIcons);
$connection->table('settings_key_value')->insert([
'key' => date('Y-m-d H:i:s'),
'value' => json_encode($currentIcons),
]);
$connection->table('settings_key_value')->updateOrInsert(
['key' => 'currentIcons'],
['value' => json_encode($currentIcons)]);
return response()->redirectToRoute('adm.icons');
}
}
110 changes: 110 additions & 0 deletions resources/views/adm/icons.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{% extends 'adm.base' %}
{% block title %}Ikony {{ parent() }}{% endblock %}

{% block card %}
{{ form_open({url: route('adm.icons.save'), method: 'post', id: 'app'}) }}
<div class="d-flex justify-content-end mb-3">
<p>
<input type="submit" value="Zapisz" class="btn btn-primary" data-submit-state="Zapisywanie...">
</p>
</div>
<table class="table table-striped">
<tr>
<td>
<input class="form-control" placeholder="Wyszukaj po nazwie..." v-model="searchName">
</td>
<td>
<input class="form-control" placeholder="Wyszukaj po ikonie..." v-model="searchIcon">
</td>
<td>
<div style="width:30px; height:35px; display:flex; align-items:center;">
<i class="fa-solid fa-magnifying-glass"></i>
</div>
</td>
</tr>
</table>
<table class="table table-striped">
<tr>
<th>Umiejscowienie</th>
<th>ikona font-awesome</th>
<th></th>
</tr>
<tr v-for="(icon, index) in editorIcons" v-show="visible(icon)">
<td>
<div class="d-flex align-items-center">
<i :class="['fa-fw', icon.defaultIcon]"></i>
<input :value="icon.location" class="form-control mx-2" disabled style="font-family:monospace;">
<i :class="['fa-fw', icon.currentIcon ]"></i>
</div>
</td>
<td>
<input
:name="'icons[' + icon.location + ']'"
v-model="icon.currentIcon"
:placeholder="icon.defaultIcon"
class="form-control"
style="font-family:monospace;"
></td>
<td>
<button
type="button"
@click="icon.currentIcon='';"
class="btn btn-sm"
:style="{visibility: icon.currentIcon ? 'visible' : 'hidden'}">
<i class="fa-solid fa-arrow-rotate-left"></i>
</button>
</td>
</tr>
</table>
{{ form_close() }}
{% endblock %}

{% block body %}
{{ parent() }}
<script
src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.min.js"
integrity="sha512-XdUZ5nrNkVySQBnnM5vzDqHai823Spoq1W3pJoQwomQja+o4Nw0Ew1ppxo5bhF2vMug6sfibhKWcNJsG8Vj9tg=="
crossorigin="anonymous"
referrerpolicy="no-referrer">
</script>
<script>
const editorIcons = {{ editorIcons|json_encode|raw }};
new Vue({
name: 'Icons',
el: '#app',
delimiters: ['${', '}'],
data() {
return {
editorIcons: Object
.entries(editorIcons)
.map(([location, [defaultIcon, currentIcon]]) => {
return {location, defaultIcon, currentIcon};
}),
searchName: '',
searchIcon: '',
};
},
methods: {
visible({location, defaultIcon, currentIcon}) {
currentIcon = currentIcon.trim();
if (this.$data.searchName) {
if (!containsCaseInsensitive(location, this.$data.searchName)) {
return false;
}
}
if (this.$data.searchIcon) {
const effectiveIcon = currentIcon === '' ? defaultIcon : currentIcon;
if (!containsCaseInsensitive(effectiveIcon, this.$data.searchIcon)) {
return false;
}
}
return true;
},
},
});
function containsCaseInsensitive(string, substring) {
return string.toLowerCase().includes(substring.toLocaleString());
}
</script>
{% endblock %}
3 changes: 3 additions & 0 deletions routes/adm.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,8 @@ function () {
$this->get('Experiments/{survey}', ['uses' => 'ExperimentsController@show'])->name('experiments.show');
$this->post('Experiments/Save', ['uses' => 'ExperimentsController@create'])->name('experiments.create');
$this->post('Experiments/{survey}/Members', ['uses' => 'ExperimentsController@updateMembers'])->name('experiments.updateMembers');

$this->get('Icons', ['uses' => 'IconsController@index'])->name('icons');
$this->post('Icons', ['uses' => 'IconsController@save'])->name('icons.save');
},
);

0 comments on commit e992db8

Please sign in to comment.