Backend-Widgets

Hallo, ist es in Shopware4 möglich, eigene Backend-Widgets zu erstellen? Ich finde dazu keine Anleitungen. Und wenn ich mir die Datei /templates/_default/backend/index/controller/widgets.js so anschaue, sind darin die vorhandenen Widgets direkt referenziert (z.B. in der Funktion „terminateStore“). Das sieht nicht gerade erweiterbar aus. Wie erstelle ich ein Widget, dass eigene Daten abfragt, ohne die vorhandenen .js-Dateien anzupassen? Grüße Kapeha

Das scheint bis jetzt noch nicht zu klappen. Die Klasse Shopware_Components_Plugin_Bootstrap stellt auch nicht mehr - wie in 3.5.x bisher üblich die Funktion createWidget bereit.

Danke! Dann bietet Shopware 4 hier also weniger Funktionalität als die alte Version? Die Widgets kann ich ja zur Not direkt in der DB unter s_core_widgets anmelden. Aber da in der widgets.js die vorhandenen Widgets fest kodiert sind, geht es an dieser Stelle nicht weiter. Kann hier einer der Entwickler etwas dazu sagen, wann die Erstellung eigener Widgets unterstützt wird?

1 Like

naja du könntest ja auch einen eigenen JS Code mit deinem Plugin ins Backend laden und dort dann deine Widget Funktionalität abbilden. Aber schön ist das nicht da gebe ich Dir Recht :frowning: Ähnlich wie mit der REST API da fehlt einfach noch zu viel und Teilweise alles etwas zu umständlich gedacht da ist mir die “alte” API drölf mal lieber :stuck_out_tongue:

Gibt es hier von Shopware etwas neues? Irgendeinen Tip, wie man ein eigenes Widget zum Laufen bringt? Ich habe ein Plugin mit eigenem PHP-Controller erstellt. Nur wie bringe ich das Widget-System dazu, mein Widget aus dem Plugin-Verzeichnis zu laden? Grüße kapeha

die widget.js könnt ihr über den block {block name=“backend/index/controller/widgets”} überschreiben…

Sicher, dass das so geht? Ich habe in meiner Bootstrap: public function onPostDispatchBackendWidgets(Enlight\_Event\_EventArgs $args) { $args-\>getSubject()-\>View()-\>addTemplateDir( $this-\>Path() . 'Views/' ); $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/bauerwidgets/store/turnover.js' ); $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/bauerwidgets/store/widget.js' ); $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/bauerwidgets/controller/widgets.js' ); $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/bauerwidgets/view/orders.js' ); } Wenn die Widgets initialisert werden, dann springt er schon einmal in das PostDispatch. Soweit funktioniert es noch… In den jeweiligen Template-Block springt er nicht mehr. Bspw.: //{block name="backend/index/view/widgets/orders" append} Ext.define('Shopware.apps.Index.view.widgets.Orders', { extend: 'Shopware.apps.Index.view.widgets.Base', alias: 'widget.swag-last-orders-widget', title: '{s name=orders/title2}Last orders test{/s}', layout: 'fit', ... //{/block} Außerdem ist mir aufgefallen, dass die Blöcke bspw. //{block name="backend/ubdex/store/visitors"} heißen. Ist das so gewollt? Für einen Tipp wäre ich sehr dankbar!

Ich habe hier ein lauffähiges Plugin erstellt. Leider werden im Backend die Dateien bei Aufruf der Widgets nicht angesprochen. Hier die Bootstrap: <?php class Shopware_Plugins_Backend_Bauerwidgets_Bootstrap extends Shopware_Components_Plugin_Bootstrap { public function install() { $event = $this->createEvent( 'Enlight\_Controller\_Action\_PostDispatch\_Backend\_Widgets', 'onPostDispatchBackendWidgets' ); $this-\>subscribeEvent($event); $event = $this-\>createEvent( 'Enlight\_Controller\_Dispatcher\_ControllerPath\_Backend\_Bauerwidgets', 'onGetControllerPathBackend' ); $this-\>subscribeEvent($event); return true; } /\*\* \* just points to the path of this controller \* \* @static \* @param Enlight\_Event\_EventArgs $args \* @return string \*/ public static function onGetControllerPathBackend(Enlight\_Event\_EventArgs $args) { return dirname(\_\_FILE\_\_) . '/Controllers/Backend/Bauerwidgets.php'; } /\*\* \* Listener of event: Enlight\_Controller\_Action\_PostDispatch\_Backend\_Widgets \* @return array \*/ public function onPostDispatchBackendWidgets(Enlight\_Event\_EventArgs $args) { $args-\>getSubject()-\>View()-\>addTemplateDir( $this-\>Path() . 'Views/' ); // if ($args-\>getRequest()-\>getActionName() === 'load') { $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/bauerwidgets/store/turnover.js' ); $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/bauerwidgets/store/widget.js' ); $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/bauerwidgets/controller/widgets.js' ); $args-\>getSubject()-\>View()-\>extendsTemplate( 'backend/bauerwidgets/view/widgets/orders.js' ); // } } /\*\* \* Get version of this plugin to display in manager \* @return array \*/ public function getVersion() { return '1.0.0'; } /\*\* \* Get label of this plugin to display in manager \* @return array \*/ public function getLabel() { return 'Bauerwidgets'; } /\*\* \* Get information of this plugin to display in manager \* @return array \*/ public function getInfo() { return array( 'version' =\> $this-\>getVersion(), 'label' =\> $this-\>getLabel(), 'author' =\> 'Mathias Bauer', 'description' =\> 'Widget Test', 'support' =\> 'keiner', 'link' =\> '' ); } } ?\> Und hier bspw. die backend/bauerwidgets/store/turnover.js //{block name="backend/ubdex/store/turnover"} append} Ext.define('Shopware.apps.Bauerwidgets.store.Turnover', { override: 'Shopware.apps.Index.store.Turnover', proxy: { type: 'ajax', url: '{url controller="bauerwidgets" action="getTurnOverVisitorsAction"}', reader: { type: 'json', root: 'data' } } }); //{/block} Und hier ein Auszug aus backend/bauerwidgets/controller/widgets.js: //{block name="backend/index/controller/widgets" append} Ext.define('Shopware.apps.Index.controller.Widgets', { extend: 'Enlight.app.Controller', /\*\* \* Shopware viewport which holds the whole application. \* @default null \* @Ext.container.Viewport \*/ viewport: null, /\*\* \* Dashboard desktop, which will be contain the widgets. \* @default null \* @Ext.container.Container \*/ desktop: null, /\*\* \* Widget holder which contains the widget columns. \* @default null \* @Shopware.apps.Index.view.widgets.Desktop \*/ widgetHolder: null, /\*\* \* Contains all stores which are necessary for the \* activated widgets. \* \* @array \*/ necessaryStores: [], /\*\* \* Counts the loaded stores to terminate if all dependencies are loaded. \* @integer \*/ loadedStores: 0, /\*\* \* Indicates that all stores are loaded. \* @boolean \*/ fullyLoaded: false, /\*\* \* Snippets for the widget controller. \* @object \*/ snippets: { titles: { allow\_merchant: '{s name=titles/allow\_merchant}Unlock merchant{/s}', decline\_merchant: '{s name=titles/decline\_merchant}Decline merchant{/s}' } }, /\*\* \* Initiliazes the widget system and sets the global settings \* for the widget system (like the rendered viewport, the \* active desktop and so on...). \* \* @public \* @return void \*/ init: function() { var me = this; console.log('im bauerwidgets controller'); me.viewport = Shopware.app.Application.viewport; // Raise error if the viewport isn't available if(!me.viewport) { Ext.Error.raise('Viewport is not loaded'); } me.desktop = me.viewport.getDesktop(0); me.control({ 'widgets-container': { savePosition: me.onSavePosition }, 'swag-merchant-widget': { allowMerchant: function( record) { me.onOpenMerchantDetail('allow', record); }, declineMerchant: function(record) { me.onOpenMerchantDetail('decline', record); } } }); me.viewport.on('resize', me.onResizeDesktop, me); me.renderViewport(false); me.callParent(arguments); }, ... }); //{/block} In Firebug wird nie eine Konsolenausgabe ausgegeben bzw. es werden immer die Orginaldateien aufgerufen. Evtl. kann sich jemand das Plugin mal installieren und mir einen Tipp geben. Danke! Grüße Mathias

Kann es sein, dass man die Widgets gar nicht erweitern kann bzw. neue erstellen? Das ist doch ein Bug seitens Shopware, oder? Hat irgendjemand schon einmal in der 4er-Version ein Widget erstellt oder erweitert? Andere Applikationen, wie z.B. die Order-Applikation, kann ich ohne Probleme erweitern und abändern. Grüße Mathias

*PUSH*

Könnte sich evtl. jemand von Shopware mal das Problem ansehen? Ich glaube, da liegt ein Bug vor. Danke!

Ich habe das Problem jetzt als Bug in den Bugtracker eingetragen. Mal sehen, ob sich da was ergibt.

Hi, ist das Problem bei euch noch akkut? Ich habe das mal nachgebaut, da scheint es mir keine grundsätzlichen Probleme zu geben. 1) Widget installieren (install() des Plugins) public function createWidget() { $widget = new Shopware\Models\Widget\Widget(); $widget-\>setLabel('Custom Widget'); $widget-\>setName('my-widget'); $this-\>Application()-\>Models()-\>persist($widget); $this-\>Application()-\>Models()-\>flush(); } 2) Backend erweitern. Event: ‚Enlight_Controller_Action_PostDispatch_Backend_Index‘ => ‚extendsBackend‘ public function extendsBackend(\Enlight\_Event\_EventArgs $args) { $this-\>bootstrap-\>registerMyTemplateDir(); $this-\>bootstrap-\>registerMySnippets(); /\*\* @var \Enlight\_Controller\_Action $controller \*/ $controller = $args-\>getSubject(); if ($controller-\>Request()-\>getActionName() != 'load') { return; } $controller-\>View()-\>extendsTemplate('backend/swag\_custom\_widget/index/widgets/my\_custom\_widget.js'); } 3) Eigenes Widget erzeugen: Besonderheit ist hier eigentlich nur, dass ich mich an einen den visitor-Block hänge, weil ich da weiß, dass Shopware.apps.Index.view.widgets.Base schon vorhanden ist. //{block name="backend/index/view/widgets/visitors" append} Ext.define('Shopware.apps.SwagCustomWidget.index.widgets.myCustomWidget', { extend: 'Shopware.apps.Index.view.widgets.Base', alias: 'widget.my-widget', layout: 'fit', initComponent: function() { var me = this; me.items = me.getItems(); me.callParent(arguments); }, getItems: function() { var me = this; return [{ xtype: 'grid', store: me.getBackendUserStore(), viewConfig: { hideLoadingMsg: true }, border: 0, columns: [{ dataIndex: 'username', header: 'Name', flex: 1 },{ dataIndex: 'lastlogin', header: 'Logged in since', flex: 1 }] }]; }, getBackendUserStore: function() { var me = this; return Ext.create('Ext.data.Store', { fields: [{ name: 'id', type: 'integer' }, { name: 'username', type: 'string' }, { name: 'lastlogin', type: 'date' },], proxy: { type: 'ajax', url: '{url controller=MyWidget action=loadBackendUser}', reader: { type: 'json', root: 'data' } }, autoLoad: true }); } }); //{/block} 4) Eigenen Controller registrieren und Daten für den Store laden (spare ich mir, sollte ja Standard sein) Es könnte da sicher noch ein paar bessere Blöcke geben - aber so vom Prinzip sollte das erstmal gehen. lG Daniel

1 Like

Das hört sich vielversprechend an. Ich werde es ausprobieren. D.h. aber auch, dass die Widgets, wie es vom Support angekündigt wurde, nicht überarbeitet werden, richtig? Grüße Mathias