Início
NexoPOS

Declaração de Widget

Um widget é um novo recurso adicionado ao NexoPOS 5x que permite a criação de partes isoladas de funcionalidades acessíveis a partir do painel (dashboard).

Anteriormente, tínhamos muitos dashboards por função. A partir deste lançamento, o dashboard será o mesmo para todos, mas a única diferença é que os widgets estão sujeitos às permissões.

Quando mencionamos que os widgets estão sujeitos a permissões, queremos dizer que alguns widgets podem exigir permissões para ficarem visíveis, quando isso está claramente declarado.

Este guia irá abranger a criação completa de um widget no NexoPOS v5.x.

Declarando o Widget

Todos os widgets são declarados na pasta “app/Widgets”. Cada classe de um widget deve estender “WidgetService”. Uma declaração típica de um widget é a seguinte:

<?php
namespace App\Widgets;

use App\Services\WidgetService;

class ProfileWidget extends WidgetService
{
    public function __construct()
    {
        // ...
    }
}

Depois de definir o widget, você precisa definir algumas propriedades úteis, que são:

  • name: Isso define como identificar e nomear o widget.
  • vueComponent: A maioria dos widgets depende de um componente Vue. O nome do objeto declarado globalmente no objeto “window” deve ser definido aqui.
  • descrição: Para descrever o que o widget faz.
  • Permissão: Tornará o widget disponível se o usuário conectado tiver a permissão fornecida.

Observe que, ao definir a permissão em uma classe de widget, essa permissão não é criada automaticamente nem atribuída aos usuários. Você deve criar e atribuir manualmente essa permissão usando um arquivo de migração dedicado.

Aqui está um exemplo completo de um widget declarado:

<?php
namespace App\Widgets;

use App\Services\WidgetService;

class ProfileWidget extends WidgetService
{
    protected $vueComponent     =   'nsProfileWidget';

    public function __construct()
    {
        $this->name     =   __( 'Profile' );
        $this->description  =   __( 'Will display a profile widget with user stats.' );
        $this->permission   =   'nexopos.see.profile-widget';
    }
}

Agora que um widget foi declarado, precisamos registrá-lo usando um Provedor de Serviços.

Registrar Widget Declarado

Um widget que não estiver registrado não será reconhecido pelo NexoPOS. Esta é uma etapa obrigatória para tornar o widget acessível a todos os usuários. Em primeiro lugar, vamos resolver a classe WidgetService em um método de inicialização (boot) do nosso provedor de serviços.

<?php
namespace App\Providers;

use App\Services\WidgetService;
use App\Widgets\ProfileWidget;
use Illuminate\Support\ServiceProvider;

class WidgetsServiceProvider extends ServiceProvider
{
    public function boot()
    {
        /**
         * @var WidgetService $widgetService
         */
        $widgetService  = app()->make( WidgetService::class );

        $widgetService->registerWidgets([
            ProfileWidget::class,
        ]);
    }
}

Depois que o widget é registrado, ele pode agora ser gerenciado por qualquer usuário que tenha permissão para vê-lo. Se um widget não fornecer nenhuma permissão, ele ficará visível para qualquer pessoa.

Declarando o Componente Vue

No momento, nosso widget não tem ninguém nem componentes Vue. Como dito anteriormente, precisamos declarar no objeto (ou contexto) “window” nosso componente Vue 3.

Para prosseguirmos, vamos registrar nosso componente assim:

import { defineAsyncComponent } from 'vue';

window[ 'nsProfileWidget' ]                 =   defineAsyncComponent( () => import( './widgets/ns-profile-widget.vue' ) );

Observe que “nsProfileWidget” corresponde ao valor da propriedade “vueComponent” definida na classe ProfileWidget. No seu caso, deve corresponder ao valor que você definiu na propriedade “vueComponent”.

Ao usar “nsProfileWidget”, deve-se atribuir a ele um valor que seja um objeto que resolva componentes de forma assíncrona. Embora os comportamentos do widget pertençam ao desenvolvedor, é altamente recomendável que cada widget inclua um botão de fechar. O botão de fechar garantirá que o widget possa ser excluído pelo usuário.

Botão Fechar

Cada botão de fechar deve emitir um evento exclusivo que é ouvido pela área do widget. Aqui está um exemplo:

<template>
    <div id="ns-best-cashiers" class="flex flex-auto flex-col shadow rounded-lg overflow-hidden">
        <div class="flex-auto">
            <div class="head text-center border-b w-full flex justify-between items-center p-2">
                <h5>Profile</h5>
                <div class="flex -mx-1">
                    <div class="px-1">
                        <ns-close-button @click="$emit( 'onRemove' )"></ns-close-button>
                    </div>
                </div>
            </div>
            <div class="body">
                <!-- put the body here -->
            </div>
        </div>
    </div>
</template>

Precisamos clicar em “ns-close-button” para emitir o evento “onRemove”. Isso garantirá que o widget possa ser removido com segurança pelo usuário.

Botão de ação

Este botão é usado para arrastar o widget pela área de dropzone. Para isso, precisamos incluir a classe “widget-handle” dentro de um elemento que queremos usar para arrastar o widget. Você deve evitar aplicar essa classe ao widget inteiro, especialmente se o seu widget incluir controles.

<template>
    <div id="ns-best-cashiers" class="flex flex-auto flex-col shadow rounded-lg overflow-hidden">
        <div class="flex-auto">
            <div class="head text-center border-b w-full flex justify-between items-center p-2">
                <h5>Profile</h5>
                <div class="flex -mx-1">
                    <div class="px-1">
                        <ns-close-button @click="$emit( 'onRemove' )"></ns-close-button>
                    </div>
                    <!-- Start Widget Handle -->
                    <div class="px-1">
                        <ns-icon-button class="widget-handle" className="la-expand-arrows-alt"></ns-icon-button>
                    </div>
                    <!-- End Widget Handle -->
                </div>
            </div>
            <div class="body">
                <!-- put the body here -->
            </div>
        </div>
    </div>
</template>