Media News
All checks were successful
Gitea Actions / Run-Tests-On-Arm64 (push) Successful in 6m7s
Gitea Actions / Run-Tests-On-Amd64 (push) Successful in 13m47s

This commit is contained in:
Thomas Peterson 2025-03-17 08:34:19 +01:00
parent f168c0fe75
commit 3e9aff64ac
9 changed files with 253 additions and 115 deletions

View File

@ -29,6 +29,7 @@
"doctrine/doctrine-bundle": "2.7.*",
"doctrine/mongodb-odm-bundle": "^4",
"doctrine/orm": "^2.7",
"dunglas/doctrine-json-odm": "^1.4",
"gabrielbull/ups-api": "dev-master",
"gregwar/captcha-bundle": "^2.2",
"guzzlehttp/guzzle": "^6",

86
src/new/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3d55fa7eafce4cc315d4e02dd640ec78",
"content-hash": "da8eba6c1fa5f895ee29628551ab79ce",
"packages": [
{
"name": "azuyalabs/yasumi",
@ -2339,6 +2339,90 @@
},
"time": "2025-01-24T11:45:48+00:00"
},
{
"name": "dunglas/doctrine-json-odm",
"version": "v1.4.2",
"source": {
"type": "git",
"url": "https://github.com/dunglas/doctrine-json-odm.git",
"reference": "c76280318ffb60aecceaf7f178298727c3dc35a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dunglas/doctrine-json-odm/zipball/c76280318ffb60aecceaf7f178298727c3dc35a5",
"reference": "c76280318ffb60aecceaf7f178298727c3dc35a5",
"shasum": ""
},
"require": {
"doctrine/orm": "^2.6.3 || ^3.0.0",
"php": ">=8.1",
"symfony/property-access": "^5.4 || ^6.0 || ^7.0",
"symfony/property-info": "^5.4 || ^6.0 || ^7.0",
"symfony/serializer": "^5.4 || ^6.0 || ^7.0"
},
"require-dev": {
"doctrine/annotations": "^1.0 || ^2.0.0",
"doctrine/dbal": "^2.7 || ^3.3 || ^4.0.0",
"doctrine/doctrine-bundle": "^1.12.13 || ^2.2",
"symfony/finder": "^5.4 || ^6.0 || ^7.0",
"symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0",
"symfony/phpunit-bridge": "^6.0 || ^7.0",
"symfony/uid": "^5.4 || ^6.0 || ^7.0",
"symfony/validator": "^5.4 || ^6.0 || ^7.0"
},
"suggest": {
"scienta/doctrine-json-functions": "To add support for JSON functions in DQL.",
"symfony/framework-bundle": "To use the provided bundle."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Dunglas\\DoctrineJsonOdm\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kévin Dunglas",
"email": "kevin@dunglas.fr",
"homepage": "https://dunglas.fr"
}
],
"description": "An object document mapper for Doctrine ORM using JSON types of modern RDBMS.",
"homepage": "https://dunglas.fr",
"keywords": [
"database",
"json",
"mysql",
"odm",
"orm",
"postgresql",
"rdbms"
],
"support": {
"issues": "https://github.com/dunglas/doctrine-json-odm/issues",
"source": "https://github.com/dunglas/doctrine-json-odm/tree/v1.4.2"
},
"funding": [
{
"url": "https://github.com/dunglas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/dunglas/doctrine-json-odm",
"type": "tidelift"
}
],
"time": "2024-11-26T13:57:21+00:00"
},
{
"name": "egulias/email-validator",
"version": "4.0.3",

View File

@ -118,6 +118,7 @@ class EditController extends AbstractController
/** @var News $news */
$news = $entityManager
->getRepository('PSC\Shop\NewsBundle\Entity\News')->findOneBy(array('uid' => $uid, 'shop' => $selectedShop));
dump($news);
$form = $this->createForm(NewsType::class, $news);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {

View File

@ -87,6 +87,7 @@ class News
#[ORM\Column(name: 'to_date', type: 'datetime')]
protected ?\DateTime $toDate;
#[ORM\Column(name: 'media', type: 'json')]
public $media = [];
/**
* enable

View File

@ -20,120 +20,11 @@
{% block body %}
<div class="w-full">
{{ form_start(form, {attr: {class: ''}}) }}
<div class="tab-group flex-none md:flex w-full" data-dui-orientation="vertical">
<div role="tablist" class="relative mr-5 rounded-sm flex flex-col p-1 w-full md:w-2/12">
<div class="absolute top-0 left-0 right-0 mx-1 text-white w-auto bg-psc-500 rounded-sm shadow-sm transition-all duration-300 transform scale-x-0 translate-x-0 tab-indicator z-0"></div>
<a href="#" class="tab-link flex items-center text-sm active px-4 py-2 relative" data-dui-tab-target="all">
<svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="button-icon">
<path d="M21 7.35304L21 16.647C21 16.8649 20.8819 17.0656 20.6914 17.1715L12.2914 21.8381C12.1102 21.9388 11.8898 21.9388 11.7086 21.8381L3.30861 17.1715C3.11814 17.0656 3 16.8649 3 16.647L2.99998 7.35304C2.99998 7.13514 3.11812 6.93437 3.3086 6.82855L11.7086 2.16188C11.8898 2.06121 12.1102 2.06121 12.2914 2.16188L20.6914 6.82855C20.8818 6.93437 21 7.13514 21 7.35304Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M3.52844 7.29357L11.7086 11.8381C11.8898 11.9388 12.1102 11.9388 12.2914 11.8381L20.5 7.27777" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M12 21L12 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M11.6914 11.8285L3.89139 7.49521C3.49147 7.27304 3 7.56222 3 8.01971V16.647C3 16.8649 3.11813 17.0656 3.30861 17.1715L11.1086 21.5048C11.5085 21.727 12 21.4378 12 20.9803V12.353C12 12.1351 11.8819 11.9344 11.6914 11.8285Z" fill="currentColor" stroke="currentColor" stroke-linejoin="round"></path>
</svg> {{ 'General'|trans }}</a>
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 text-gray-700 relative" data-dui-tab-target="text">
<svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="button-icon">
<path d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M4.271 18.3457C4.271 18.3457 6.50002 15.5 12 15.5C17.5 15.5 19.7291 18.3457 19.7291 18.3457" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M12 12C13.6569 12 15 10.6569 15 9C15 7.34315 13.6569 6 12 6C10.3431 6 9 7.34315 9 9C9 10.6569 10.3431 12 12 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
</svg> {{ 'Text'|trans }}</a>
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 text-gray-700 relative" data-dui-tab-target="media">
<svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="button-icon">
<path d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M4.271 18.3457C4.271 18.3457 6.50002 15.5 12 15.5C17.5 15.5 19.7291 18.3457 19.7291 18.3457" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M12 12C13.6569 12 15 10.6569 15 9C15 7.34315 13.6569 6 12 6C10.3431 6 9 7.34315 9 9C9 10.6569 10.3431 12 12 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
</svg> {{ 'Media'|trans }}</a>
{% for customGroup in customGroups %}
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 text-gray-700 relative" data-dui-tab-target="{{ customGroup.id }}">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" />
</svg>
{{ customGroup.title }} </a>
{% endfor %}
</div>
<div class="rounded-sm w-full border bg-white p-5 bg-lime-600 shadow-lg dark:border-strokedark dark:bg-boxdark">
<div id="all" class="tab-content w-full text-stone-500 text-sm block grid grid-col-4">
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">
{{ 'General'|trans }}
</h6>
<div class="flex flex-wrap">
<div class="w-full lg:w-6/12 px-4">
{{ form_row(form.title) }}
</div>
<div class="w-full lg:w-6/12 px-4">
{{ form_row(form.url) }}
</div>
</div>
<div class="flex flex-wrap">
<div class="w-full md:w-2/12 px-4 content-center">
{{ form_widget(form.enable)}}
</div>
<div class="w-full md:w-5/12 px-4">
{{ form_row(form.sortDate)}}
</div>
<div class="w-full md:w-5/12 px-4">
{{ form_row(form.language)}}
</div>
</div>
<div class="flex flex-wrap">
<div class="w-full md:w-5/12 px-4">
{{ form_row(form.fromDate)}}
</div>
<div class="w-full md:w-5/12 px-4">
{{ form_row(form.toDate)}}
</div>
</div>
<div class="w-full px-4">
{{ form_row(form.introduction)}}
</div>
</div>
<div id="text" class="tab-content w-full text-stone-500 text-sm hidden p-4">
{{ form_widget(form.text) }}
</div>
<div id="media" class="tab-content w-full text-stone-500 text-sm hidden p-4">
<twig:MediaForm :form="form" :media="news" />
<table class="table table-borderless form-no-mb">
<thead>
<tr>
<td>Name</td>
<td>Description</td>
</tr>
</thead>
<tbody>
{% for media_form in form.media %}
<tr>
<td>
{{ form_row(media_form.name) }}
</td>
<td>
{{ form_row(media_form.description) }}
</td>
<td>
{{ form_row(media_form.vars.button_delete, {label: 'X', attr: {class: 'btn btn-outline-danger'}}) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ form_widget(form.media.vars.button_add, {label: '+ Add Media', attr: {class: 'btn btn-outline-primary'}}) }}
</div>
{% for customGroup in customGroups %}
<div class="tab-pane" id="{{ customGroup.id }}" role="tabpanel">
{% for customField in customFields %}
{% if customField.group == customGroup.id and customField.getTemplate %}
{{ include(customField.getTemplate, {form: form}) }}
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>
</div>
<div class="text-end my-2">
{{ form_widget(form.save, {attr: {class: 'psc-button-save'}}) }}
</div>
{{ form_end(form) }}
{{ component('NewsForm', {
form: form,
news: news,
customGroups: customGroups
}) }}
</div>
<h4 class="text-psc text-xl font-medium flex flex-row gap-1 mb-2">

View File

@ -0,0 +1,118 @@
<div {{attributes}}>
{{ form_start(form, {attr: {class: ''}}) }}
<div class="tab-group flex-none md:flex w-full" data-dui-orientation="vertical">
<div role="tablist" class="relative mr-5 rounded-sm flex flex-col p-1 w-full md:w-2/12">
<div class="absolute top-0 left-0 right-0 mx-1 text-white w-auto bg-psc-500 rounded-sm shadow-sm transition-all duration-300 transform scale-x-0 translate-x-0 tab-indicator z-0"></div>
<a href="#" class="tab-link flex items-center text-sm active px-4 py-2 relative" data-dui-tab-target="all">
<svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="button-icon">
<path d="M21 7.35304L21 16.647C21 16.8649 20.8819 17.0656 20.6914 17.1715L12.2914 21.8381C12.1102 21.9388 11.8898 21.9388 11.7086 21.8381L3.30861 17.1715C3.11814 17.0656 3 16.8649 3 16.647L2.99998 7.35304C2.99998 7.13514 3.11812 6.93437 3.3086 6.82855L11.7086 2.16188C11.8898 2.06121 12.1102 2.06121 12.2914 2.16188L20.6914 6.82855C20.8818 6.93437 21 7.13514 21 7.35304Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M3.52844 7.29357L11.7086 11.8381C11.8898 11.9388 12.1102 11.9388 12.2914 11.8381L20.5 7.27777" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M12 21L12 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M11.6914 11.8285L3.89139 7.49521C3.49147 7.27304 3 7.56222 3 8.01971V16.647C3 16.8649 3.11813 17.0656 3.30861 17.1715L11.1086 21.5048C11.5085 21.727 12 21.4378 12 20.9803V12.353C12 12.1351 11.8819 11.9344 11.6914 11.8285Z" fill="currentColor" stroke="currentColor" stroke-linejoin="round"></path>
</svg> {{ 'General'|trans }}</a>
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 text-gray-700 relative" data-dui-tab-target="text">
<svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="button-icon">
<path d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M4.271 18.3457C4.271 18.3457 6.50002 15.5 12 15.5C17.5 15.5 19.7291 18.3457 19.7291 18.3457" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M12 12C13.6569 12 15 10.6569 15 9C15 7.34315 13.6569 6 12 6C10.3431 6 9 7.34315 9 9C9 10.6569 10.3431 12 12 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path>
</svg> {{ 'Text'|trans }}</a>
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 text-gray-700 relative" data-dui-tab-target="media">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
</svg> {{ 'Media'|trans }}</a>
{% if customGroups is defined %}
{% for customGroup in customGroups %}
<a href="#" class="tab-link flex items-center text-sm px-4 py-2 text-gray-700 relative" data-dui-tab-target="{{ customGroup.id }}">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" />
</svg>
{{ customGroup.title }} </a>
{% endfor %}
{% endif %}
</div>
<div class="rounded-sm w-full border bg-white p-5 bg-lime-600 shadow-lg dark:border-strokedark dark:bg-boxdark">
<div id="all" class="tab-content w-full text-stone-500 text-sm block grid grid-col-4">
<h6 class="text-sm mt-3 mb-6 font-bold uppercase">
{{ 'General'|trans }}
</h6>
<div class="flex flex-wrap">
<div class="w-full lg:w-6/12 px-4">
{{ form_row(form.title) }}
</div>
<div class="w-full lg:w-6/12 px-4">
{{ form_row(form.url) }}
</div>
</div>
<div class="flex flex-wrap">
<div class="w-full md:w-2/12 px-4 content-center">
{{ form_widget(form.enable)}}
</div>
<div class="w-full md:w-5/12 px-4">
{{ form_row(form.sortDate)}}
</div>
<div class="w-full md:w-5/12 px-4">
{{ form_row(form.language)}}
</div>
</div>
<div class="flex flex-wrap">
<div class="w-full md:w-5/12 px-4">
{{ form_row(form.fromDate)}}
</div>
<div class="w-full md:w-5/12 px-4">
{{ form_row(form.toDate)}}
</div>
</div>
<div class="w-full px-4">
{{ form_row(form.introduction)}}
</div>
</div>
<div id="text" class="tab-content w-full text-stone-500 text-sm hidden p-4">
{{ form_widget(form.text) }}
</div>
<div id="media" class="tab-content w-full text-stone-500 text-sm hidden p-4">
<table class="table table-borderless form-no-mb">
<thead>
<tr>
<td>Name</td>
<td>Description</td>
</tr>
</thead>
<tbody>
{% for media_form in form.media %}
<tr>
<td>
{{ form_row(media_form.name) }}
</td>
<td>
{{ form_row(media_form.description) }}
</td>
<td>
{{ form_row(media_form.vars.button_delete, {label: 'X', attr: {class: 'btn btn-outline-danger'}}) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ form_widget(form.media.vars.button_add, {label: '+ Add Media', attr: {class: 'btn btn-outline-primary'}}) }}
</div>
{% if customGroups is defined %}
{% for customGroup in customGroups %}
<div class="tab-pane" id="{{ customGroup.id }}" role="tabpanel">
{% for customField in customFields %}
{% if customField.group == customGroup.id and customField.getTemplate %}
{{ include(customField.getTemplate, {form: form}) }}
{% endif %}
{% endfor %}
</div>
{% endfor %}
{% endif %}
</div>
</div>
<div class="text-end my-2">
{{ form_widget(form.save, {attr: {class: 'psc-button-save'}}) }}
</div>
{{ form_end(form) }}
</div>

View File

@ -0,0 +1,32 @@
<?php
namespace PSC\Shop\NewsBundle\Twig;
use PSC\Shop\NewsBundle\Entity\News;
use PSC\Shop\NewsBundle\Form\Backend\NewsType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\LiveCollectionTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;
#[AsLiveComponent(template: '@PSCShopNews/components/NewsForm.html.twig')]
class NewsForm extends AbstractController
{
use DefaultActionTrait;
use LiveCollectionTrait;
#[LiveProp(fieldName: 'formData')]
public ?News $news;
public ?Array $customGroups;
protected function instantiateForm(): FormInterface
{
return $this->createForm(
NewsType::class,
$this->news
);
}
}

View File

@ -8,5 +8,6 @@ class Version20250313154423 extends Base
{
$this->entityManager->getConnection()->exec("ALTER TABLE news ADD from_date datetime NULL DEFAULT null");
$this->entityManager->getConnection()->exec("ALTER TABLE news ADD to_date datetime NULL DEFAULT null");
$this->entityManager->getConnection()->exec("ALTER TABLE news ADD media json NULL DEFAULT null");
}
}

View File

@ -97,6 +97,15 @@
"doctrine/sql-formatter": {
"version": "1.2.x-dev"
},
"dunglas/doctrine-json-odm": {
"version": "1.4",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "0.1",
"ref": "c2ab78f625df0c89af5908d50a28602ff8c4919f"
}
},
"egulias/email-validator": {
"version": "2.1.18"
},