Managing Module Settings

The module you are building can add and manage settings, the settings can be user modifiable with settings page in the dashboard or internal for the module itself.

Make sure to always prefix your settings keys with your module name for example: invoices_billing_enabled to prevent conflicts with other modules that may possibly use the same settings key.

Using Settings Internally

Concord CRM ships with settings function that can be used to retrieve, store and update settings related to your module, when your module does not provide settings that can be adjusted by an admin you can use this function directly in your code to store specific settings that can be retrieved and user anywhere in the module codebase.

if(settings('invoices_billing_enabled')) {
    //
}

Updating and Adding Settings

To update settings, you can use the settings function which as shown below:

settings()->set('invoices_billing_enabled', false)->save();

To save multiple settings you can provide an array to the set method.

settings()->set([
    'invoices_billing_enabled'=>false,
    'invoices_other_feature_enabled'=>true
])->save();

Checking If Setting Exist

To check if setting key exist, you can use the has method, for example when the module is activated and you want to ensure that the a specific setting has default value, see example below that registers a listener in the module service provider:

public function boot() : void
{
    $this->app['events']->listen('modules.invoices.enabled', function() {
        if(!settings()->has('invoices_billing_enabled')) {
            settings()->set('invoices_billing_enabled', false)->save();
        }
    });
}

Add Settings Page

Only admins can access the settings page in Concord CRM

If the module you are creating needs to have user configureable settings page that will be displayed in the dashboard, you will need to register a settings menu item and front-end route view that will display the settings form.

Register Settings Menu Item

Concord CRM will automatically register the settings menu items provided in the module service provider, to achieve this, in the module service provider create a method settingsMenu and provide the items that needs to be registered.

To register multiple items, the settingsMenu method should return an array of items.

use Modules\Core\Facades\Innoclapps;
use Modules\Core\Facades\SettingsMenu;
use Modules\Core\Settings\SettingsMenuItem;

protected function settingsMenu() : SettingsMenuItem
{
    return SettingsMenuItem::make('invoices', __('invoices::settings.title'))
        ->path('/invoices')
        ->icon('CurrencyDollar')
        ->order(41);
}

The first argument of the SettingsMenuItem class's make method is the item unique identifier (ID) and the second argument is the label/title of the item.

To add collapsable menu item, you should provide third argument as an array that will include the children items.

SettingsMenuItem::make('invoices', __('invoices::settings.title'), [
    SettingsMenuItem::make('billing', 'Invoices')->path('/invoices/billing'),
    SettingsMenuItem::make('payments', 'Payments')->path('/invoices/payments'),
])->icon('CurrencyDollar')->order(41)

Register Frontend Settings Route

Next, we will need to register a route for the front-end that will display the settings form that the user can use to perform update.

// modules/Invoices/resources/js/app.js

import { translate } from "core/i18n";

import SettingsInvoices from "./views/SettingsInvoices.vue";

if (window.Innoclapps) {
    Innoclapps.booting(function (app, router) {
        router.addRoute("settings", {
            path: "invoices", // "/settings/invoices"
            component: SettingsInvoices,
            meta: {
                title: translate("invoices::settings.title"),
            },
        });
    });
}

Here is a quick example from the SettingsInvoices.vue Vue component.

<template>
    <ICardHeader>
        <ICardHeading :text="$t('invoices::settings.title')" />
    </ICardHeader>

    <ICard :overlay="!componentReady">
        <ICardBody>
            <IFormSwitchField>
                <IFormSwitchLabel :text="$t('invoices::settings.auto_send')" />

                <IFormSwitchDescription
                    :text="$t('invoices::settings.auto_send_info')"
                />

                <IFormSwitch
                    v-model="form.invoices_auto_send"
                    @change="submit"
                />
            </IFormSwitchField>
        </ICardBody>
    </ICard>
</template>

<script setup>
    import { useSettings } from "@/Core/composables/useSettings";

    const { form, submit, isReady: componentReady } = useSettings();
</script>

Make sure that you are running a dev server with the npm run dev command and then navigate to settings and click on the menu item you have added before.

The submit function within the useSettings composable will update the form settings, you are not required to write a controller and route for the settings.

Include Submit Button

In many cases the settings may include dropdown, input fields that the user needs to fill then click on a button to save the settings, you can add a form that on submittion will call submit function.

<template>
    <form @submit.prevent="submit">
        <ICard :overlay="!componentReady">
            <ICardBody>
                <div>
                    <IFormLabel class="mb-1">Label</IFormLabel>
                    <IFormInput v-model="form.module_setting_key" />
                </div>
            </ICardBody>

            <ICardFooter class="text-right">
                <IButton
                    type="submit"
                    variant="primary"
                    :disabled="form.busy"
                    :text="$t('core::app.save')"
                />
            </ICardFooter>
        </ICard>
    </form>
</template>
<script setup>
    import { useSettings } from "@/Core/composables/useSettings";

    const { form, submit, isReady: componentReady } = useSettings();
</script>