backports murph-skeleton
This commit is contained in:
parent
3bf661d059
commit
f1fce6d6db
|
@ -54,6 +54,7 @@ export default {
|
|||
}
|
||||
|
||||
if (['image/png', 'image/jpg', 'image/jpeg', 'image/gif'].indexOf(this.mime) === -1) {
|
||||
this.thumbnail = null
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
<li class="breadcrumb-item" v-for="item in breadcrumb">
|
||||
<a class="btn btn-sm" href="#" v-on:click="setDirectory(item.path)" v-html="item.label"></a>
|
||||
</li>
|
||||
<li v-if="isLoading" class="ml-3">
|
||||
<div class="spinner-border spinner-border-sm" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<div class="d-flex">
|
||||
|
@ -200,7 +205,8 @@ export default {
|
|||
files: [],
|
||||
parent: null,
|
||||
modalUrl: null,
|
||||
ajax: 0
|
||||
ajax: 0,
|
||||
isLoading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -266,17 +272,22 @@ export default {
|
|||
},
|
||||
refresh () {
|
||||
const that = this
|
||||
this.isLoading = true
|
||||
this.files = []
|
||||
this.directories = []
|
||||
|
||||
axios.get(Routing.generate('admin_file_manager_api_directory', {
|
||||
directory: that.directory,
|
||||
context: that.context,
|
||||
ajax: this.ajax
|
||||
ajax: this.ajax,
|
||||
time: Date.now(),
|
||||
}))
|
||||
.then((response) => {
|
||||
that.buildBreadcrum(response.data.breadcrumb)
|
||||
that.parent = response.data.parent
|
||||
that.directories = response.data.directories
|
||||
that.files = response.data.files
|
||||
that.isLoading = false
|
||||
|
||||
const query = new URLSearchParams(window.location.search)
|
||||
query.set('path', that.directory)
|
||||
|
|
|
@ -64,8 +64,19 @@ module.exports = function () {
|
|||
fileManagerBrowser((value) => {
|
||||
value = value.replace(/^\//, '')
|
||||
|
||||
picker.parent('.form-filepicker-container').find('input.form-filepicker-picker').val(value)
|
||||
picker.parents('.form-filepicker-container').find('input.form-filepicker-picker').val(value)
|
||||
input.val(value)
|
||||
})
|
||||
})
|
||||
|
||||
$('body').on('click', '.form-filepicker-reset', (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
const button = $(e.target)
|
||||
const id = '#' + button.attr('data-target')
|
||||
const input = $(id)
|
||||
|
||||
input.val('')
|
||||
button.parents('.form-filepicker-container').find('input.form-filepicker-picker').val('')
|
||||
})
|
||||
}
|
||||
|
|
|
@ -25,8 +25,15 @@ const openModal = function (url) {
|
|||
|
||||
module.exports = function () {
|
||||
let click = 0
|
||||
const body = $('body')
|
||||
|
||||
$('body').on('click', '*[data-modal]', (e) => {
|
||||
body.on('hidden.bs.modal', '.modal', (e) => {
|
||||
if ($('.modal.show').length) {
|
||||
$('body').addClass('modal-open')
|
||||
}
|
||||
})
|
||||
|
||||
body.on('click', '*[data-modal]', (e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ use Symfony\Component\HttpFoundation\Request;
|
|||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use App\Core\Event\Page\PageEditEvent;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
class PageAdminController extends CrudController
|
||||
{
|
||||
|
@ -50,12 +52,17 @@ class PageAdminController extends CrudController
|
|||
EntityManager $entityManager,
|
||||
RepositoryQuery $repositoryQuery,
|
||||
PageLocator $pageLocator,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
Request $request
|
||||
): Response {
|
||||
$entity = $repositoryQuery->filterById($entity)->findOne();
|
||||
|
||||
$event = new PageEditEvent($entity);
|
||||
$eventDispatcher->dispatch($event, PageEditEvent::FORM_INIT_EVENT);
|
||||
|
||||
$this->getConfiguration()->setFormOptions('edit', [
|
||||
'pageConfiguration' => $pageLocator->getPage(get_class($entity)),
|
||||
'page_configuration' => $pageLocator->getPage(get_class($entity)),
|
||||
'page_builder_options' => $event->getPageBuilderOptions(),
|
||||
]);
|
||||
|
||||
return $this->doEdit($entity, $entityManager, $request);
|
||||
|
|
|
@ -28,6 +28,7 @@ class CrudConfiguration
|
|||
protected array $isSortableCollection = [];
|
||||
protected string $sortableCollectionProperty = 'sortOrder';
|
||||
protected ?string $defaultLocale = null;
|
||||
protected bool $showActions = true;
|
||||
|
||||
protected static $self;
|
||||
|
||||
|
@ -314,4 +315,16 @@ class CrudConfiguration
|
|||
{
|
||||
return $this->sortableCollectionProperty;
|
||||
}
|
||||
|
||||
public function setShowActions(bool $showActions): self
|
||||
{
|
||||
$this->showActions = $showActions;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getShowActions(): bool
|
||||
{
|
||||
return $this->showActions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ class FileInformation implements EntityInterface
|
|||
|
||||
public function getAttributes()
|
||||
{
|
||||
return json_decode($this->attributes, true);
|
||||
return (array) json_decode($this->attributes, true);
|
||||
}
|
||||
|
||||
public function setAttributes($attributes): self
|
||||
|
|
|
@ -225,12 +225,30 @@ class Node implements EntityInterface
|
|||
/**
|
||||
* @return Collection|Node[]
|
||||
*/
|
||||
public function getChildren(): Collection
|
||||
public function getChildren(array $criteria = []): Collection
|
||||
{
|
||||
if (null === $this->children) {
|
||||
$this->children = new ArrayCollection();
|
||||
}
|
||||
|
||||
if (!empty($criteria)) {
|
||||
$children = new ArrayCollection();
|
||||
|
||||
foreach ($this->children as $child) {
|
||||
$add = true;
|
||||
|
||||
if (isset($criteria['visible']) && $child->getIsVisible() !== $criteria['visible']) {
|
||||
$add = false;
|
||||
}
|
||||
|
||||
if ($add) {
|
||||
$children->add($child);
|
||||
}
|
||||
}
|
||||
|
||||
return $children;
|
||||
}
|
||||
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
|
@ -256,7 +274,7 @@ class Node implements EntityInterface
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getAllChildren(): ArrayCollection
|
||||
public function getAllChildren(array $criteria = []): ArrayCollection
|
||||
{
|
||||
$children = [];
|
||||
|
||||
|
@ -274,6 +292,14 @@ class Node implements EntityInterface
|
|||
return $a->getTreeLeft() < $b->getTreeLeft() ? -1 : 1;
|
||||
});
|
||||
|
||||
if (!empty($criteria)) {
|
||||
foreach ($children as $key => $child) {
|
||||
if (isset($criteria['visible']) && $child->getIsVisible() !== $criteria['visible']) {
|
||||
unset($children[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayCollection($children);
|
||||
}
|
||||
|
||||
|
@ -308,6 +334,19 @@ class Node implements EntityInterface
|
|||
return $string->startsWith('http://') || $string->startsWith('https://');
|
||||
}
|
||||
|
||||
public function hasAppUrl(): bool
|
||||
{
|
||||
$string = u($this->getUrl());
|
||||
|
||||
foreach (['tel:', 'fax:', 'mailto:'] as $prefix) {
|
||||
if ($string->startsWith($prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getIsVisible(): ?bool
|
||||
{
|
||||
return $this->isVisible;
|
||||
|
|
|
@ -140,7 +140,7 @@ class Page implements EntityInterface
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,13 @@ class NodeEventSubscriber extends EntityManagerEventSubscriber
|
|||
$generatedUrl = $generatedUrl.'-'.$number;
|
||||
}
|
||||
|
||||
if (!u($generatedUrl)->startsWith('https://') && !u($generatedUrl)->startsWith('http://')) {
|
||||
if (
|
||||
!u($generatedUrl)->startsWith('https://')
|
||||
&& !u($generatedUrl)->startsWith('http://')
|
||||
&& !u($generatedUrl)->startsWith('tel:')
|
||||
&& !u($generatedUrl)->startsWith('mailto:')
|
||||
&& !u($generatedUrl)->startsWith('fax:')
|
||||
) {
|
||||
$generatedUrl = '/'.$generatedUrl;
|
||||
$generatedUrl = preg_replace('#/{2,}#', '/', $generatedUrl);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ class CollectionBlockType extends AbstractType
|
|||
{
|
||||
$builder->add(
|
||||
'value',
|
||||
CollectionType::class,
|
||||
$options['collection_type'],
|
||||
array_merge([
|
||||
'required' => false,
|
||||
'label' => false,
|
||||
|
@ -40,6 +40,7 @@ class CollectionBlockType extends AbstractType
|
|||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Block::class,
|
||||
'collection_type' => CollectionType::class,
|
||||
'collection_name' => '',
|
||||
'label_add' => 'Add',
|
||||
'label_delete' => 'Delete',
|
||||
|
|
|
@ -105,7 +105,7 @@ class PageType extends AbstractType
|
|||
'choices' => call_user_func(function () use ($options) {
|
||||
$choices = [];
|
||||
|
||||
foreach ($options['pageConfiguration']->getTemplates() as $template) {
|
||||
foreach ($options['page_configuration']->getTemplates() as $template) {
|
||||
$choices[$template['name']] = $template['file'];
|
||||
}
|
||||
|
||||
|
@ -119,14 +119,15 @@ class PageType extends AbstractType
|
|||
]
|
||||
);
|
||||
|
||||
$builder->getData()->buildForm($builder);
|
||||
$builder->getData()->buildForm($builder, $options['page_builder_options']);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Page::class,
|
||||
'pageConfiguration' => null,
|
||||
'page_configuration' => null,
|
||||
'page_builder_options' => [],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"Page": "Page"
|
||||
"Administration": "Administration"
|
||||
"Users": "Utilisateurs"
|
||||
"New user": "Nouvel utilisateur⋅trice"
|
||||
"Back to the list": "Retour à la liste"
|
||||
"Edit": "Éditer"
|
||||
"New password": "Nouveau mot de passe"
|
||||
|
|
|
@ -139,9 +139,11 @@
|
|||
</th>
|
||||
{% endblock %}
|
||||
{% endfor %}
|
||||
<th class="crud-action-column col-2 miw-100 text-right">
|
||||
{{ 'Actions'|trans }}
|
||||
</th>
|
||||
{% if configuration.showActions %}
|
||||
<th class="crud-action-column col-2 miw-100 text-right">
|
||||
{{ 'Actions'|trans }}
|
||||
</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
{% endblock %}
|
||||
|
@ -205,34 +207,36 @@
|
|||
</td>
|
||||
{% endfor %}
|
||||
|
||||
<td class="crud-action-column col-2 miw-200 text-right">
|
||||
{% block list_item_actions_before %}{% endblock %}
|
||||
{% if configuration.showActions %}
|
||||
<td class="crud-action-column col-2 miw-200 text-right">
|
||||
{% block list_item_actions_before %}{% endblock %}
|
||||
|
||||
{% if configuration.action(context, 'show', true) %}
|
||||
<a href="{{ path(configuration.pageRoute('show'), {entity: item.id}|merge(configuration.pageRouteParams('show'))) }}" class="btn btn-sm btn-secondary mr-1">
|
||||
<span class="fa fa-eye"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if configuration.action(context, 'show', true) %}
|
||||
<a href="{{ path(configuration.pageRoute('show'), {entity: item.id}|merge(configuration.pageRouteParams('show'))) }}" class="btn btn-sm btn-secondary mr-1">
|
||||
<span class="fa fa-eye"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if configuration.action(context, 'edit', true) %}
|
||||
<a href="{{ path(configuration.pageRoute('edit'), {entity: item.id}|merge(configuration.pageRouteParams('edit'))) }}" class="btn btn-sm btn-primary mr-1">
|
||||
<span class="fa fa-edit"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if configuration.action(context, 'edit', true) %}
|
||||
<a href="{{ path(configuration.pageRoute('edit'), {entity: item.id}|merge(configuration.pageRouteParams('edit'))) }}" class="btn btn-sm btn-primary mr-1">
|
||||
<span class="fa fa-edit"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if configuration.action(context, 'delete', true) %}
|
||||
<button type="submit" form="form-delete-{{ item.id }}" class="btn btn-sm btn-danger">
|
||||
<span class="fa fa-trash"></span>
|
||||
</button>
|
||||
{% if configuration.action(context, 'delete', true) %}
|
||||
<button type="submit" form="form-delete-{{ item.id }}" class="btn btn-sm btn-danger">
|
||||
<span class="fa fa-trash"></span>
|
||||
</button>
|
||||
|
||||
<form method="post" action="{{ path(configuration.pageRoute('delete'), {entity: item.id}|merge(configuration.pageRouteParams('delete'))) }}" id="form-delete-{{ item.id }}" data-form-confirm>
|
||||
<input type="hidden" name="_method" value="DELETE">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ item.id) }}">
|
||||
</form>
|
||||
{% endif %}
|
||||
<form method="post" action="{{ path(configuration.pageRoute('delete'), {entity: item.id}|merge(configuration.pageRouteParams('delete'))) }}" id="form-delete-{{ item.id }}" data-form-confirm>
|
||||
<input type="hidden" name="_method" value="DELETE">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ item.id) }}">
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% block list_item_actions_after %}{% endblock %}
|
||||
</td>
|
||||
{% block list_item_actions_after %}{% endblock %}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -44,14 +44,14 @@
|
|||
{% for child in item %}
|
||||
{{ form_row(child) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="text-right">
|
||||
<span data-collection-delete-container class="btn btn-sm btn-danger">
|
||||
<span data-collection-delete="{{ loop.index }}">
|
||||
{{ label_delete|trans }}
|
||||
<div class="text-right">
|
||||
<span data-collection-delete-container class="btn btn-sm btn-danger">
|
||||
<span data-collection-delete="{{ loop.index }}">
|
||||
{{ label_delete|trans }}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@ -145,19 +145,27 @@
|
|||
|
||||
<div class="p-2 text-center">
|
||||
<span class="form-filepicker-container">
|
||||
<input class="form-control form-filepicker-picker mb-3" data-target="{{ id }}" readonly type="text" value="{{ value }}">
|
||||
<span class="btn btn-sm btn-primary form-filepicker-picker" data-target="{{ id }}">
|
||||
<div class="input-group mb-3">
|
||||
<input class="form-control form-filepicker-picker" data-target="{{ id }}" readonly type="text" value="{{ value }}">
|
||||
<div class="input-group-append form-filepicker-reset" data-target="{{ id }}">
|
||||
<div class="input-group-text btn" data-target="{{ id }}">
|
||||
<span class="fa fa-backspace" data-target="{{ id }}"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="btn btn-sm btn-primary form-filepicker-picker mb-1" data-target="{{ id }}">
|
||||
{{ 'Choose'|trans }}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
{% if value %}
|
||||
{% if value.pathname is defined %}
|
||||
<a class="btn btn-sm btn-success ml-1" href="{{ asset(value.pathname) }}" target="_blank">
|
||||
<a class="btn btn-sm btn-success ml-1 mb-1" href="{{ asset(value.pathname) }}" target="_blank">
|
||||
{{ 'Download'|trans }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="btn btn-sm btn-success ml-1" href="{{ asset(value) }}" target="_blank">
|
||||
<a class="btn btn-sm btn-success ml-1 mb-1" href="{{ asset(value) }}" target="_blank">
|
||||
{{ 'Download'|trans }}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
|
|
@ -87,6 +87,10 @@
|
|||
<a href="{{ safe_node_url(node) }}" class="btn btn-sm border border-secondary btn-light">
|
||||
<span class="fa fa-sign-out-alt text-muted"></span>
|
||||
</a>
|
||||
{% elseif node.hasAppUrl %}
|
||||
<a href="{{ node.url }}" class="btn btn-sm border border-secondary btn-light">
|
||||
<span class="fa fa-sign-out-alt text-muted"></span>
|
||||
</a>
|
||||
{% else %}
|
||||
{% if not node.disableUrl %}
|
||||
{% if node.parameters|length %}
|
||||
|
|
|
@ -57,6 +57,10 @@ class SiteRouteLoader extends Loader
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($node->hasAppUrl()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null !== $node->getAliasNode()) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ class SiteStore
|
|||
public function getNavigations(): array
|
||||
{
|
||||
return $this->navigationRepositoryQuery->create()
|
||||
->orderBy('.sortOrder')
|
||||
->find()
|
||||
;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use Symfony\Component\Form\FormBuilderInterface;
|
|||
*/
|
||||
class RssPage extends Page
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add(
|
||||
'title',
|
||||
|
|
|
@ -13,7 +13,7 @@ use Symfony\Component\Form\FormBuilderInterface;
|
|||
*/
|
||||
class SimplePage extends TitledPage
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
parent::buildForm($builder);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use App\Core\Entity\Site\Page\Page;
|
|||
*/
|
||||
class TextPage extends Page
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add(
|
||||
'content',
|
||||
|
|
|
@ -13,7 +13,7 @@ use Symfony\Component\Form\FormBuilderInterface;
|
|||
*/
|
||||
class TitledPage extends Page
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add(
|
||||
'title',
|
||||
|
|
|
@ -36,8 +36,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|||
<meta property="og:description" content="{{ _page.ogDescription }}" />
|
||||
|
||||
{% if _page.ogImage %}
|
||||
<meta property="og:image" content="{{ asset(_page.ogImage) }}" />
|
||||
<meta property="og:image:secure_url" content="{{ asset(_page.ogImage) }}" />
|
||||
<meta property="og:image" content="{{ absolute_url(asset(_page.ogImage)) }}" />
|
||||
<meta property="og:image:secure_url" content="{{ absolute_url(asset(_page.ogImage)) }}" />
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in a new issue