New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nova Action Index Field Package #44

Open
dillingham opened this Issue Sep 16, 2018 · 5 comments

Comments

Projects
None yet
5 participants
@dillingham
Collaborator

dillingham commented Sep 16, 2018

Package to add a link that triggers a resource action on a specific row of a resource's index view.

ID Name Activate
1 Brian Activate
2 Sarah Activate

Maybe add some method chaining for link options

public function fields()
{
        return [
            Action::make('ActivateUser')
        ];
}

Options

->onRelations()
->text('Activate')
->elseText(‘Activated’)
->vueIf(‘user.activated == false’)

inspired from this conversation
laravel/nova-issues#188

@alexbowers

This comment has been minimized.

alexbowers commented Sep 16, 2018

I have found a way to make a modal open on the index page on an action. I'll publish how once I work out any kinks with it.

@dillingham

This comment has been minimized.

Collaborator

dillingham commented Sep 16, 2018

@alexbowers awesome!

Maybe also useful to add a method for adding conditional logic. Ie ->displayWhen $user->activated is false.

Also an option to display if only on index, not relationships. Activating users when users are a hasmany on a different resource might not make sense. Ie event attendees don’t need activating.

@DianaR19

This comment has been minimized.

DianaR19 commented Nov 13, 2018

What package is it?

@Gaia-Nutrition

This comment has been minimized.

Gaia-Nutrition commented Nov 26, 2018

@alexbowers Could you share how you managed to open the Modal?
The problem I currently face is the fact that the <action-selector> components (which I could overwrite) only mounts if one or more resources are selected.
I was trying to overwrite the <action-selector> component and use Nova.$on() to listen for global events triggered from inside a custom field...

@alexbowers

This comment has been minimized.

alexbowers commented Nov 26, 2018

Sure @Gaia-Nutrition @dillingham

This was a work in progress that I haven't touched in a while, but I assume that the fundamentals still are there for it to work.

In an IndexField.vue file, I have something like the following:

<template>
    <span>
        <span class="inline-block w-3 cursor-pointer" @click.prevent="openConfirmationModal">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M20 18.35V19a1 1 0 0 1-1 1h-2A17 17 0 0 1 0 3V1a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4c0 .56-.31 1.31-.7 1.7L3.16 8.84c1.52 3.6 4.4 6.48 8 8l2.12-2.12c.4-.4 1.15-.71 1.7-.71H19a1 1 0 0 1 .99 1v3.35z"/></svg>
        </span>

        <transition name="fade">
            <phone-call-modal 
                v-if="confirmActionModalOpened"
                @close="closeConfirmationModal"
            />
        </transition>

        {{ field.value }}
    </span>
</template>

<script>
    import PhoneCallModal from './PhoneCallModal';

    export default {
        props: ['resourceName', 'field'],
        components: {
            'phone-call-modal': PhoneCallModal,
        },
        data() {
            return {
                confirmActionModalOpened: false,
            }
        },
        methods: {
            openConfirmationModal() {
                this.confirmActionModalOpened = true
            },

            closeConfirmationModal() {
                this.confirmActionModalOpened = false
            },
        },
    }
</script>

And in a PhoneCallModal.vue file I have

<template>
    <modal
        class="modal"
        tabindex="-1"
        role="dialog"
        @modal-close="handleClose"
    >
        <div class="bg-white rounded-lg shadow-lg overflow-hidden w-460">
            <h2 class="pt-8 px-8">Making phone call</h2>
            <p class="text-80 px-8 my-8">This is my message</p>

            <div class="bg-30 px-6 py-3 flex">
                <div class="flex items-center ml-auto">
                    <button
                        type="button"
                        class="btn btn-default btn-primary"
                        @click="makeCall"
                    >
                        <span>Start Call</span>
                    </button>
                </div>
            </div>
        </div>        
    </modal>
</template>

<script>
    import Modal from '@/components/Modal';

    export default {
        components: {
            'modal': Modal,
        },
        props: {
            phoneNumber: String,
        },
        created() {
            this.init();
        },
        methods: {
            makeCall() {
                // ... Do something
            },
            init() {
                // ... Do something
            },
            /**
             * Stop propogation of input events unless it's for an escape or enter keypress
             */
            handleKeydown(e) {
                if (['Escape', 'Enter'].indexOf(e.key) !== -1) {
                    return
                }

                e.stopPropagation()
            },

            /**
             * Execute the selected action.
             */
            handleConfirm(e) {
                this.$emit('confirm')
            },

            /**
             * Close the modal.
             */
            handleClose() {
                this.$emit('close')
            },
        },
    }
</script>


<style scoped>
    .w-460 {
        width: 460px;
    }
</style>

You'll notice the @/components/Modal line, this refers to a component built into Nova JS.

To get it to work like that I have modified the webpack.mix.js file to have the following:

let mix = require('laravel-mix')

mix.js('resources/js/field.js', 'dist/js')
.webpackConfig({
    resolve: {
        symlinks: false,
        alias: {
            '@': path.resolve(__dirname, 'vendor/laravel/nova/resources/js/'),
        },
    }
});

This isn't strictly necessary, since you could work your way to the nova JS files yourself in the modal itself, however, I find this easier to deal with since you can refactor code moving the files around without that action itself causing things to break.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment