Coder Social home page Coder Social logo

Comments (6)

milewski avatar milewski commented on August 10, 2024

Hi, can you share some sample code? I'm not sure what you mean by on HasMany Relationship table, I have only tested this package when using it on the main INDEX view of a resource... not on hasMany tables... I'm unsure how it worked before as I had never that use case in mind...

from nova-mega-filter.

didix16 avatar didix16 commented on August 10, 2024

Sure, here you have:

Suppose I have a class BusinessUnit which is a Nova Resource and is something like:

<?php

namespace App\Nova;

use Illuminate\Http\Request;
use Laravel\Nova\Fields\HasMany;
use Laravel\Nova\Fields\Text;

class BusinessUnit extends Resource {

    /**
     * The model the resource corresponds to.
     *
     * @var string
     */
    public static $model = 'App\Models\BusinessUnit';

    // ....

    /**
     * Get the fields displayed by the resource.
     *
     * @param Request $request
     * @return array
     */
    public function fields(Request $request)
    {
        return [
            Text::make(__("name"), "name")
                ->rules([
                    'required',
                    'max:255'
                ])
                ->canSeeWhen("viewField", [$this, "name"])
                ->canEditWhen("editField", [$this, "name"]),
            HasMany::make(__("Events"), "events", Event::class)
                ->withMeta([
                    "name" => __("Events that has this business unit")
                ])
                ->canSeeWhen("viewRelation", [$this, "events"])
                ->canEditWhen("editRelation", [$this, "events"]),
        ];
    }

// ...

}

Also suppose I have a class Event that is a Nova Resource like this:

<?php

namespace App\Nova;

use App\Nova\Actions\EventFavoriteAction;
use App\Nova\Fields\Event\ActorEventFields;
use App\Nova\Fields\Event\ArtistEventFields;
use App\Nova\Fields\Event\BudgetControlFields;
use App\Nova\Fields\Event\CreativeFields;
use App\Nova\Fields\Event\FileFields;
use App\Nova\Fields\Event\FinanceFields;
use App\Nova\Fields\Event\ImageFields;
use App\Nova\Fields\Event\MainFields;
use App\Nova\Fields\Event\MarketingFields;
use App\Nova\Fields\Event\MerchandisingFields;
use App\Nova\Fields\Event\ProductionFields;
use App\Nova\Fields\Event\ThemeFields;
use App\Nova\Fields\Event\TicketFields;
use App\Nova\Fields\Event\TransportFields;
use App\Nova\Fields\Event\VipFields;
use App\Services\CacheService;
//...
use DigitalCreative\MegaFilter\Column;
use DigitalCreative\MegaFilter\HasMegaFilterTrait;
use DigitalCreative\MegaFilter\MegaFilter;
// ...
use Laravel\Nova\Fields\HasMany;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Panel;

class Event extends Resource
{
    use HasMegaFilterTrait;

    /**
     * The model the resource corresponds to.
     *
     * @var string
     */
    public static $model = 'App\Models\Event';

    /**
     * Get the fields displayed by the resource.
     *
     * @param Request $request
     * @return array
     */
    public function fields(Request $request)
    {
        return [
            new Panel(__("Event Details"), new MainFields($this, $request)),
            new Panel(__("Files"), new FileFields($this, $request)),
            new Panel(__("Themes"), new ThemeFields($this, $request)),
            new Panel(__("Images"), new ImageFields($this, $request)),
            new Panel(__("Tickets"), new TicketFields($this, $request)),
            new Panel(__("Transport"), new TransportFields($this, $request)),
            new Panel(__("Creative"), new CreativeFields($this, $request)),
            new Panel(__("Marketing"), new MarketingFields($this, $request)),
            new Panel(__("Production"), new ProductionFields($this, $request)),
            new Panel(__("Finance"), new FinanceFields($this, $request)),
            new Panel(__("VIP"), new VipFields($this, $request)),
            new Panel(__("Merchandising"), new MerchandisingFields($this, $request)),
            new Panel(__("Budgets Control"), new BudgetControlFields($this, $request)),

            BelongsToMany::make("Artists")
                ->withMeta([
                    "name" => __("Booked artists")
                ])
                ->canSeeWhen("viewRelation", [$this, "artists"])
                ->canEditWhen("editRelation", [$this, 'artists'])
                ->fields(new ArtistEventFields($this, $request)),

            // ....

            Boolean::make("Has sponsors", function (){
                return $this->resource->sponsors()->get()->count() > 0;
            })->withMeta([
                "name" => __("Has sponsors")
            ])
            ->onlyOnIndex(),
            HasMany::make(__("sponsors"), "sponsors", Sponsor::class)
                ->showOnIndex(false),
        ];
    }

    /**
     * Get the cards available for the request.
     *
     * @param Request $request
     * @return array
     */
    public function cards(Request $request)
    {
        /**
         * @var CacheService $cacheService
         */
        $cacheService = app("cache.service");

        $user = $request->user();
        $resource = class_basename($this->resource);

        $CACHE_KEY = $cacheService->generateKey("megafilter", "resource", $resource, $user->id);

        // Check CACHE. If we have stored some data then get that data, else compute the data
        if ($cacheService->isHit($CACHE_KEY)){

            // Also check if the user has modified the megafilter. If it has, then invalidate the cache
            $MEGA_FILTER_CACHE_KEY = $cacheService->generateKey("megafilterHash", "resource", $resource, $user->id);

            $megafilterHash = $request->get("megaFilter"); // *<== I'VE CHANGED THIS IN version 0.6.0 but nothing changed*
            $currentMegafilterHash = $cacheService->rememberForever($MEGA_FILTER_CACHE_KEY, function () use($megafilterHash){
                return $megafilterHash;
            });

            if ($megafilterHash === $currentMegafilterHash){

                $columns = $cacheService->get($CACHE_KEY);
                return [
                    MegaFilter::make([
                        "columns" => $columns
                    ]),
                ];

            }else {
                $cacheService->delete($MEGA_FILTER_CACHE_KEY);
                $cacheService->delete($CACHE_KEY);
            }
        }


        // Get event field list
        $fields = Schema::getColumnListing("events");

        // Remove unwanted fields
        $fields = array_diff($fields, ["deleted_at", "show_form"]);


        // filter only the fields that the user can see
        $fields = array_filter($fields, function ($v) use(&$user){
            return
                (
                    $user->hasPermission("VIEW_FIELD_" . strtoupper($v) . "_EVENTS") ||
                    $user->hasPermission("VIEW_RELATION_" . strtoupper($v) . "_EVENTS")
                );

        });

        // Replace original field name for model name to properly get the related entity as value and show it to index list
        $repl = $this->resource->getRenamedFields();

        $fields = array_map(function ($v) use ($repl){
            return $repl[$v] ?? $v;
        }, $fields);


        // Define which field should be checked by default
        $checked = [
            "ideo", "code", "city", "capacity", "start_at", "country", "eventstatus"
        ];

        // The array containing Column instances to apply on MegaFilter
        $columns = [];
        foreach ($fields as $field){
            if (!empty($checked) && ($idx = array_search($field, $checked)) !== FALSE ){
                $columns[] = Column::make(model_field_trans($this, $field), $field)->checked();
                array_splice($checked, $idx, 1);
            }else{
                $columns[] = Column::make(model_field_trans($this, $field), $field);
            }

        }

        /**
         * ****************************
         * COMPUTED COLUMNS
         * ****************************
         */
        $columns[] = Column::make("Theme", "theme")->checked();
        $columns[] = Column::make("Has sponsors")->permanent();
        $columns[] = Column::make('CM', 'cm')->checked(false);

        $columns = $cacheService->rememberForever($CACHE_KEY, function () use($columns){
            return $columns;
        });

        return [
            MegaFilter::make([
                "columns" => $columns
            ]),
        ];
    }
    // ....
}

from nova-mega-filter.

milewski avatar milewski commented on August 10, 2024

Does it work when you open /resources/events?

/resources/business-units <-- this package was not meant to be working on this page, imagine you could have multiple hasMany fields on your BusinessUnits resource... how the filters would be merged... how to know a specific column is targeting the first hasMany not the second.. etc...

from nova-mega-filter.

didix16 avatar didix16 commented on August 10, 2024

It works on /resources/events and /resources/business-units. If it has multiple HasMany fields, it applies each filter correctly. For example: if i have and entity A with HasMany entity B, if I define the columns on B, then the HasMany on A works. Also if A has HasMany to C and C has the megafilter with its columns, also applies it. I think the filter that is applying is the last made on /resources/B or /resources/C.

If it was not meant to be working like this, well, it does and for me its a nice feature because i don't want to list all the columns since my Event model has a lot, like 30 or more....

from nova-mega-filter.

milewski avatar milewski commented on August 10, 2024

Yes I understand, I guess you are only relying on the columns being hidden/visible on the HasMany relation tables, not the actual "Mega Filter" card that is injected on the top of the page... I'm not sure what changed since the version you had it working... it probably was on this commit/ release: v0.3.0...master

I think you could try to return true on this function here to see if it fixes the issue for you... if so then might just be a matter of figuring out a way to identify what is on the request that is being done to fetch the HasMany relation and return true..

private function shouldApplyMegaFilter(NovaRequest $request): bool
{
$controller = $request->route()->controller;
if ($controller instanceof ActionController && $request->method() === 'POST') {
return true;
}
if ($request->viaRelationship() ||
$controller instanceof ResourceShowController) {
return false;
}
return $controller instanceof FilterController
|| $controller instanceof ResourceIndexController
|| $controller instanceof ResourceCountController;
}

from nova-mega-filter.

didix16 avatar didix16 commented on August 10, 2024

Ok then, I'll try it later, test it and I'll tell you if it worked.

Thanks 👍

from nova-mega-filter.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.