Skip to content

Commit

Permalink
Prepare minipaint controllers
Browse files Browse the repository at this point in the history
  • Loading branch information
markus-moser committed Dec 10, 2024
1 parent fe70120 commit ea978d3
Show file tree
Hide file tree
Showing 3 changed files with 291 additions and 1 deletion.
7 changes: 6 additions & 1 deletion config/pimcore/routing.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
pimcore_studio_ui:
resource: "@PimcoreStudioUiBundle/src/Controller/"
resource: "@PimcoreStudioUiBundle/src/Controller/DefaultController.php"
type: annotation
prefix: '%pimcore_studio_ui.url_path%'

pimcore_studio_ui_backend:
resource: "@PimcoreStudioUiBundle/src/Controller/ImageEditorController.php"
type: annotation
prefix: '%pimcore_studio_backend.url_prefix%'

85 changes: 85 additions & 0 deletions src/Controller/ImageEditorController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
declare(strict_types=1);

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

namespace Pimcore\Bundle\StudioUiBundle\Controller;


use Pimcore\Bundle\StudioBackendBundle\Security\Service\SecurityServiceInterface;
use Pimcore\Bundle\StudioBackendBundle\Util\Constant\ElementPermissions;
use Pimcore\Model\Asset;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Attribute\Route;

final class ImageEditorController extends AbstractController
{
public function __construct (
private readonly SecurityServiceInterface $securityService,
)
{
}

#[Route('/image-editor', methods: ['GET'])]
public function editorAction(Request $request): Response {
$asset = Asset\Image::getById((int) $request->get('id'));

if (!$asset) {
throw $this->createNotFoundException('Asset not found');
}

$this->securityService->hasElementPermission(
$asset,
$this->securityService->getCurrentUser(),
ElementPermissions::VIEW_PERMISSION
);


return $this->render('@PimcoreStudioUi/image-editor/editor.html.twig', [
'asset' => $asset
]);
}

#[Route('/get-asset', name: 'studio_temp_get_asset', methods: ['GET'])]
public function getAssetAction(Request $request): StreamedResponse
{
$image = Asset::getById((int)$request->get('id'));

if (!$image) {
throw $this->createNotFoundException('Asset not found');
}

$this->securityService->hasElementPermission(
$image,
$this->securityService->getCurrentUser(),
ElementPermissions::VIEW_PERMISSION
);

$stream = $image->getStream();

if (!is_resource($stream)) {
throw $this->createNotFoundException('Unable to get resource for asset ' . $image->getId());
}

return new StreamedResponse(function () use ($stream) {
fpassthru($stream);
}, 200, [
'Content-Type' => $image->getMimeType(),
'Access-Control-Allow-Origin' => '*',
]);
}
}
200 changes: 200 additions & 0 deletions templates/image-editor/editor.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
.cursor-pointer {
cursor: pointer;
}
</style>
<base href="/bundles/pimcoreadmin/js/lib/minipaint/" />
{{ encore_entry_script_tags('imageEditor', null, 'pimcoreAdminImageEditor') }}
</head>
<body>
<div class="wrapper">
<nav aria-label="Main Menu" class="main_menu" id="main_menu"></nav>

<div class="submenu">
<div class="block attributes" id="action_attributes"></div>
<div class="clear"></div>
<button class="undo_button" id="undo_button" type="button">
<span class="sr_only">Undo</span>
</button>
</div>

<div class="sidebar_left" id="tools_container"></div>

<div class="middle_area" id="middle_area">

<canvas class="ruler_left" id="ruler_left"></canvas>
<canvas class="ruler_top" id="ruler_top"></canvas>

<div class="main_wrapper" id="main_wrapper">
<div class="canvas_wrapper" id="canvas_wrapper">
<div id="mouse"></div>
<div class="transparent-grid" id="canvas_minipaint_background"></div>
<canvas id="canvas_minipaint">
<div class="trn error">
Your browser does not support canvas or JavaScript is not enabled.
</div>
</canvas>
</div>
</div>
</div>

<div class="sidebar_right">
<div class="preview block">
<h2 class="trn toggle" data-target="toggle_preview">Preview</h2>
<div id="toggle_preview"></div>
</div>

<div class="colors block">
<h2 class="trn toggle" data-target="toggle_colors">Colors</h2>
<input
title="Click to change color"
type="color"
class="color_area"
id="main_color"
value="#0000ff" />
<div class="content" id="toggle_colors"></div>
</div>

<div class="block" id="info_base">
<h2 class="trn toggle toggle-full" data-target="toggle_info">Information</h2>
<div class="content" id="toggle_info"></div>
</div>

<div class="details block" id="details_base">
<h2 class="trn toggle toggle-full" data-target="toggle_details">Layer details</h2>
<div class="content" id="toggle_details"></div>
</div>

<div class="layers block">
<h2 class="trn">Layers</h2>
<div class="content" id="layers_base"></div>
</div>
</div>
</div>
<div class="mobile_menu">
<button class="left_mobile_menu" id="left_mobile_menu_button" type="button">
<span class="sr_only">Toggle Menu</span>
</button>
<button class="right_mobile_menu" id="mobile_menu_button" type="button">
<span class="sr_only">Toggle Menu</span>
</button>
</div>
<div class="hidden" id="tmp"></div>
<div id="popups"></div>

{% set imageFileExtension = pimcore_file_extension(asset.getFilename()) %}
{% set imageUrl = path('studio_temp_get_asset', {id: asset.getId()}) %}

{% if imageFileExtension not in ['png', 'jpg', 'jpeg'] %}
{% set imageUrl = path('pimcore_admin_asset_getimagethumbnail', {id: asset.getId(), format: 'png' }) %}
{% endif %}

<img style="visibility: hidden" id='image' src="{{ imageUrl }}" />
<script {{ pimcore_csp.getNonceHtmlAttribute()|raw }}>
/**
* wait for image editor to be fully available
* before loading image to editor
*/
async function loadEditor(e) {
return new Promise(resolve => {
var checkInterval = setInterval(() => {
if (window.Layers) {
clearInterval(checkInterval);
manipulateMenuBar();
loadImageToEditor(e);
resolve(true);
}
}, 300);
});
}
function loadImageToEditor(e) {
var image = document.getElementById('image');
window.Layers.insert({
name: "{{ asset.getFilename() }}",
type: 'image',
data: image,
width: image.naturalWidth || image.width,
height: image.naturalHeight || image.height,
width_original: image.naturalWidth || image.width,
height_original: image.naturalHeight || image.height,
});
document.getElementById('save_button').addEventListener('click', function () {
var tempCanvas = document.createElement("canvas");
var tempCtx = tempCanvas.getContext("2d");
var dim = window.Layers.get_dimensions();
tempCanvas.width = dim.width;
tempCanvas.height = dim.height;
Layers.convert_layers_to_canvas(tempCtx);
var dataUri = tempCanvas.toDataURL('image/{{ imageFileExtension == "png" ? "png" : "jpeg" }}');
parent.Ext.Ajax.request({
url: "{{ path('pimcore_admin_asset_imageeditorsave', {id: asset.getId()}) }}",
method: 'PUT',
params: {
dataUri: dataUri
}
});
return false;
});
}
function manipulateMenuBar() {
const menuBar = document.getElementsByClassName('menu_bar')[0];
const liElement = document.createElement('li');
const aElement = document.createElement('a');
const spanElement = document.createElement('span');
aElement.setAttribute('id', 'save_button');
aElement.setAttribute('role', 'menu_item');
aElement.setAttribute('tabindex', '-1');
aElement.setAttribute('aria-haspopup', 'false');
aElement.classList.add('cursor-pointer');
aElement.setAttribute('aria-expanded', 'false');
spanElement.setAttribute('class', 'name trn');
spanElement.innerText = parent.t('save');
aElement.appendChild(spanElement);
liElement.appendChild(aElement);
menuBar.prepend(liElement);
document.getElementById('main_menu_0_0').addEventListener('click', () => {
document.getElementById('main_menu_1_10').remove();
document.getElementById('main_menu_1_11').remove();
})
removeHref();
document.getElementsByTagName('nav')[0].addEventListener('click', (e) => {
removeHref();
});
}
function removeHref() {
const allLinkElements = document.getElementsByTagName('nav')[0].querySelectorAll("a");
for (let a of allLinkElements) {
if (a.getAttribute('href') === 'javascript:void(0)') {
a.classList.add('cursor-pointer');
a.removeAttribute('href');
}
}
}
window.addEventListener("load", function(e) {
loadEditor(e);
}, false);
</script>

</body>
</html>

0 comments on commit ea978d3

Please sign in to comment.