├── .github └── funding.yml ├── .gitignore ├── basics.md ├── basics ├── helpers.md ├── localization.md ├── navigation.md ├── page.md └── screens │ ├── navigation.jpg │ ├── page_slots.jpg │ ├── page_title.jpg │ └── page_view.jpg ├── charts ├── area.md ├── bar.md ├── basics.md ├── donut.md ├── number.md ├── progress.md └── screens │ ├── bar.png │ ├── donut.png │ ├── number.png │ ├── progress.png │ └── variants.png ├── configuration.md ├── crud ├── actions.md ├── forms.md ├── index.md ├── model.md ├── screens │ ├── action_modal_fields.png │ ├── message_danger.png │ ├── message_info.png │ ├── message_success.png │ ├── message_warning.png │ ├── preview.gif │ └── search.png ├── search.md ├── show.md └── table.md ├── fields ├── block.md ├── boolean.md ├── checkboxes.md ├── conditions.md ├── date-time.md ├── icon.md ├── image.md ├── input.md ├── introduction.md ├── list.md ├── masks.md ├── modal.md ├── password.md ├── radio.md ├── range.md ├── relation.md ├── route.md ├── screens │ ├── conditions │ │ └── conditions_radio.gif │ ├── datetime │ │ ├── date_and_time.png │ │ └── example.png │ ├── image │ │ ├── expand.png │ │ └── first_big.png │ ├── range │ │ └── example.png │ ├── relation │ │ ├── inline.png │ │ ├── picker.jpg │ │ └── tags.png │ └── validation │ │ └── validation_1.png ├── select.md ├── textarea.md ├── validation.md └── wysiwyg.md ├── frontend ├── components.md ├── javascript.md └── vue.md ├── installation.md ├── packages ├── .DS_Store ├── 2fa.md ├── bladesmith.md ├── location.md ├── meta.md ├── pages.md ├── rehearsal.md └── screens │ ├── lazy.png │ ├── maps.png │ ├── nav-field.png │ ├── nav-result.png │ ├── pages_screen.jpg │ └── verify.gif ├── prologue ├── about.md ├── art.md ├── contribution.md ├── screens │ ├── cbl.jpeg │ ├── elements.jpeg │ ├── iter-font.jpeg │ ├── jb.jpeg │ └── logo-colors.jpeg ├── sponsorware.md └── upgrade.md └── readme.md /.github/funding.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [litstack] 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /basics.md: -------------------------------------------------------------------------------- 1 | # Basics 2 | 3 | ## Introduction 4 | 5 | This document describes the main components that help to understand how a 6 | litstack application is built. 7 | 8 | ## The `./lit` Folder 9 | 10 | After [installing](../installation.md) Litstack the `./lit` folder is created in 11 | your laravel application. Think of it as an its own **isolated** laravel 12 | application in your laravel application. It contains the `./lit/resources` 13 | folder containing assets and views, an `./lit/app` folder with the php classes 14 | for your **Litstack** app and other folders that are also present in the root 15 | folder. 16 | 17 | ::: tip 18 | 19 | Isolating your administration application from your app provides a clear 20 | structure of your actual business logic. 21 | 22 | ::: 23 | 24 | ## Creator Commands 25 | 26 | For almost every creator commands provided by laravel, there is a similar one 27 | that creates the corresponding files into the `./lit` folder. The commands use 28 | the `lit` prefix instead of `make`. 29 | 30 | ```shell 31 | php artisan lit:controller 32 | php artisan lit:request 33 | php artisan lit:job 34 | ``` 35 | 36 | ### Livewire 37 | 38 | There is a creator command for livewire as well: 39 | 40 | ```php 41 | php artisan lit:livewire Counter 42 | ``` 43 | 44 | ## Permissions 45 | 46 | Litstack brings a simple user-friendly permissions handler. Additionally there 47 | is an easy way to create or delete the existing permissions using the migration 48 | `./database/migrations/______________________make_permissions.php`. 49 | 50 | Configure the desired permission groups in it and create them with the artisan 51 | command `lit:permissions`. 52 | 53 | ```shell 54 | php artisan lit:permissions 55 | ``` 56 | 57 | ::: tip 58 | 59 | Add the `lit:permissions` command to your **deploy** script to keep the 60 | permissions in your production database up to date. 61 | 62 | ::: 63 | -------------------------------------------------------------------------------- /basics/helpers.md: -------------------------------------------------------------------------------- 1 | # Helpers 2 | 3 | ## Introduction 4 | 5 | The package includes a variety of global helper **PHP** `functions`. 6 | 7 | ::: tip 8 | 9 | The package includes useful **Vue** `mixins` as well. Read the 10 | [Vue mixins](../frontend/vue.md#mixins) section to learn more about the existing 11 | `mixins`. 12 | 13 | ::: 14 | 15 | ## Lit Facade 16 | 17 | The `Lit` singleton contains some helpers which are related to the application. 18 | 19 | ### `installed()` 20 | 21 | The `installed` method checks if the package has been installed. This can be 22 | useful in service providers. 23 | 24 | ```php 25 | use Ignite\Support\Facades\Lit; 26 | 27 | if(! Lit::installed()) { 28 | return; 29 | } 30 | ``` 31 | 32 | ### `route($name)` 33 | 34 | If a route is added to the route file `lit/routes/web.php`, the prefix `lit` is 35 | added to the name. The helper route also adds this prefix as well. Depending on 36 | your preferences you can use the laravel helper `route` or the Litstack helper 37 | to call up a route. 38 | 39 | ```php 40 | // lit/routes/web.php 41 | 42 | Route::get('dashboard', DashboardController::class)->name('dashboard'); 43 | ``` 44 | 45 | ```php 46 | Dashboard 47 | // Is the same as: 48 | Dashboard 49 | ``` 50 | 51 | ### `url($url)` 52 | 53 | If you don't want to use the route name to call a route but directly specify the 54 | url, you can use the `url` helper which prepends the `route_prefix` from the 55 | config **lit.php** to your url. 56 | 57 | ```php 58 | Dashboard 59 | ``` 60 | 61 | ## Miscellaneous 62 | 63 | ### `__lit($key, $replace)` 64 | 65 | The `__lit` method returns the translation using the application locale for the 66 | authenticated user. 67 | 68 | ```php 69 | __lit('messages.welcome', ['name' => 'Spatie']) 70 | ``` 71 | 72 | ### `fa($group, $icon)` 73 | 74 | The `fa` helper makes it easy to include 75 | [Fontawesome](https://fontawesome.com/icons?d=gallery) icons. 76 | 77 | ```php 78 | fa('home') // 79 | fa('fal', 'abacus') // 80 | ``` 81 | 82 | ### `lit()` 83 | 84 | The `lit` method returns the `Ignite\Support\Facades\Lit` singelton. 85 | 86 | ```php 87 | lit()->installed(); 88 | 89 | // Is the same as: 90 | 91 | use Ignite\Support\Singletons\Lit; 92 | Lit::installed(); 93 | ``` 94 | 95 | ### `lit_user()` 96 | 97 | The `lit_user` method returns the authenticated user model. 98 | 99 | ```php 100 | {{ lit_user()->email }} 101 | ``` 102 | -------------------------------------------------------------------------------- /basics/localization.md: -------------------------------------------------------------------------------- 1 | # Localization 2 | 3 | ## Introduction 4 | 5 | The application can be managed multilingual. The translation of your admin panel can 6 | be done in `php` using 7 | [laravel's localization](https://laravel.com/docs/7.x/localization) service or 8 | in `vue` using 9 | [vue-i18n](https://kazupon.github.io/vue-i18n/docs/formatting.html). It uses the 10 | **laravel** syntax for translation string. All translation strings are formatted so they can be used 11 | in `vue-i18n` as well. 12 | 13 | In Laravel applications that include the litstack package, there are **two** different 14 | locales, one for your website and one for the admin application. So for example, 15 | a user can manage german content in the admin application and still see the 16 | interface in the english version. 17 | 18 | The following examples refer to the translations which look like this: 19 | 20 | ```php{lit/resources/lang/en/messages.php} 21 | return [ 22 | "welcome": "Welcome, :name" 23 | ]; 24 | ``` 25 | 26 | ## Configuration 27 | 28 | ### Translating Litstack 29 | 30 | Translations of the admin panel are managed in the [litstack/lang](https://github.com/litstack/lang) repository, if it doesn't contain your language, you are welcome to contribute. The languages in which your admin panel should be translatable can be specified in the `lit.translatable` config. 31 | 32 | ### Translating App 33 | 34 | You can configure the translatability of your app in the `config/translatable.php` config. 35 | 36 | ::: tip 37 | 38 | If more than one locale is specified, form fields can be edited in multiple languages. 39 | 40 | ::: 41 | 42 | ## PHP 43 | 44 | To translate your admin panel using the locale of the authenticated litstack user, the `__lit()` helper method is 45 | used, just like `__()` from laravel's 46 | [localization](https://laravel.com/docs/7.x/localization#retrieving-translation-strings). 47 | 48 | ```php 49 | __lit('messages.welcome', ['name', 'Jannes']) 50 | ``` 51 | 52 | Pluralization can be used with the `__lit_choice` function or the short version 53 | `__lit_c`. 54 | 55 | ```php 56 | 'apples' => '{0} There are none|[1,19] There are some|[20,*] There are many', 57 | 58 | ... 59 | 60 | __lit_choice('apples', 10) 61 | __lit_c('apples', 10) 62 | ``` 63 | 64 | ## Vue 65 | 66 | In `Vue` the [vue-i18n](https://kazupon.github.io/vue-i18n/introduction.html) 67 | format is used. 68 | 69 | ```javascript 70 | 75 | ``` 76 | 77 | ::: tip 78 | 79 | You may also use the Laravel localization helpers in Vue components. 80 | 81 | - \_\_() 82 | - trans() 83 | - trans_choice() 84 | 85 | ::: 86 | 87 | ## Determine Locale 88 | 89 | To determine the locale the function `getLocale` can be used on the `Lit` facade 90 | like this: 91 | 92 | ```php 93 | use Ignite\Support\Facades\Lit; 94 | 95 | $litLocale = Lit::getLocale(); 96 | 97 | if (Lit::isLocale('en')) { 98 | // 99 | } 100 | ``` 101 | 102 | ## Add Path 103 | 104 | By default the path `lit/resources/lang` is imported for the admin translation. 105 | You can register any number of paths with localization files in your service 106 | providers. However, it is recommended to keep the translations for the admin 107 | application and your website separate. 108 | 109 | ```php 110 | use Ignite\Support\Facades\Lang; 111 | 112 | Lang::addPath(base_path('yourpath/lang/')); 113 | ``` 114 | 115 | ::: tip 116 | 117 | All translation attributes are merged, which makes it easy to extend existing 118 | localizations for parts like **validation** or others. 119 | 120 | ::: 121 | -------------------------------------------------------------------------------- /basics/navigation.md: -------------------------------------------------------------------------------- 1 | # Navigation 2 | 3 | ## Introduction 4 | 5 | Your admin app by default contains two navigations: the **topbar** and your 6 | **main** navigation. 7 | 8 | Both navigation instances are configured in 9 | `lit/app/Config/NavigationConfig.php` which looks as follows: 10 | 11 | ```php{lit/app/Config/NavigationConfig.php} 12 | class NavigationConfig extends Config 13 | { 14 | public function topbar(Navigation $nav) 15 | { 16 | // Build your topbar navigation in here. 17 | } 18 | 19 | public function main(Navigation $nav) 20 | { 21 | // Build your main navigation in here. 22 | } 23 | } 24 | ``` 25 | 26 | ![navigation](./screens/navigation.jpg 'navigation') 27 | 28 | ### Topbar 29 | 30 | The **topbar** navigation is meant for managing less important parts of your 31 | application, such as language and/or permissions. 32 | 33 | ### Main 34 | 35 | The **main** navigation is intended to provide quick access to the important 36 | components of your application. These could be for example Models or page 37 | content. Entries of the main navigation can be divided into 38 | [sections](#sections), additionally [groups](#groups) can be created which are 39 | displayed as a dropdown. More than one depth is not possible here. 40 | 41 | ## Building the Navigation 42 | 43 | The following explains how the navigations are built. The procedure is the same 44 | for the **topbar** and the **main** navigation. With a difference that only the 45 | **main** navigation can contain groups. 46 | 47 | ### Sections 48 | 49 | A section can contain a list of entries. An optional title can be prepended to 50 | the entries like shown in the example: 51 | 52 | ```php 53 | $nav->section([ 54 | 55 | // The Section title describes the following set of navigation entries. 56 | $nav->title('Bookings'), 57 | 58 | ... 59 | ]); 60 | ``` 61 | 62 | ### Entry 63 | 64 | Simple entries have a `title`, a `link`, and an `icon`. The 65 | [Font Awesome](https://fontawesome.com/icons?d=gallery&m=free) icons are 66 | included by default. 67 | 68 | ```php 69 | $nav->entry('Home', [ 70 | 'link' => route('your.route'), // Route 71 | 'icon' => '' // Font Awesome icon 72 | ]), 73 | ``` 74 | 75 | ### Groups 76 | 77 | Create nested navigation entries in groups. 78 | 79 | ```php 80 | $nav->group([ 81 | 'title' => 'Pages', 82 | 'icon' => '', 83 | ], [ 84 | 85 | $nav->entry(...), 86 | ... 87 | 88 | ]), 89 | ``` 90 | 91 | ### Authorization 92 | 93 | To hide navigation entries from users without the necessary permission, an 94 | `authorize` closure can be specified in which permissions for the logged in 95 | litstack user can be queried. 96 | 97 | ```php 98 | use Ignite\User\Models\User; 99 | 100 | $nav->entry('Home', [ 101 | // ... 102 | 103 | 'authorize' => function(User $user) { 104 | return $user->can('read page-home'); 105 | } 106 | ]), 107 | ``` 108 | 109 | ### Presets 110 | 111 | To build navigation entries, for example for Crud models, you can use navigation 112 | presets in which the corresponding `route` and `authorization` have already been 113 | defined. This is useful in most cases, especially to maintain the correct 114 | `authorization`. To edit the entry further you can specify an array with the 115 | navigation entry elements in a second parameter. 116 | 117 | ```php 118 | $nav->preset('crud.departments', [ 119 | 'icon' => fa('building') 120 | ]), 121 | ``` 122 | 123 | ::: tip 124 | 125 | A list of all registered navigation presets can be displayed with 126 | `php artisan lit:nav`. 127 | 128 | ::: 129 | -------------------------------------------------------------------------------- /basics/page.md: -------------------------------------------------------------------------------- 1 | # Page 2 | 3 | ## Introduction 4 | 5 | Pages are a fundamental part of the package. They provide a convenient and yet 6 | powerful way to configure pages for the Vue application in PHP. They can be 7 | used to integrate **Blade Views**, **Vue components** or ready-made components 8 | such as **charts** or form fields for models. 9 | 10 | Pages are used to configure forms with fields, index pages, dashboards with 11 | charts or basically any kind of page for the admin backend. 12 | 13 | ## Create a Page 14 | 15 | A page can be simply created by returning an instance of `Ignite\Page\Page` like 16 | so: 17 | 18 | ```php 19 | namespace Lit\Controllers; 20 | 21 | use Ignite\Page\Page; 22 | 23 | class MyPageController 24 | { 25 | public function __invoke() 26 | { 27 | $page = new Page; 28 | 29 | return $page->title('My Page'); 30 | } 31 | } 32 | ``` 33 | 34 | This will show an empty page with the title `My Page`: 35 | 36 | ![Page with Title](./screens/page_title.jpg 'Page with Title') 37 | 38 | ## View 39 | 40 | You can easily integrate your own blade components with using `view`: 41 | 42 | ```php 43 | $page = new Page; 44 | 45 | $page->view('hello'); 46 | 47 | return $page->title('My Page'); 48 | ``` 49 | 50 | ```php 51 |
52 |
53 |
54 |

Hello World!

55 |
56 |
57 |
58 | ``` 59 | 60 | And voila we have our first Page with content saying `Hello World!` using pure 61 | Blade. 62 | 63 | ![Page with View](./screens/page_view.jpg 'Page with View') 64 | 65 | ## Component 66 | 67 | Just like Blade Views, Vue components can be easily integrated into your page. 68 | To do this, the **name** of the desired Vue component must be passed as the 69 | first parameter to the `component method: 70 | 71 | ```php 72 | $page->component('my-component'); 73 | ``` 74 | 75 | You may also pass a **prop** to the component: 76 | 77 | ```php 78 | $page->component('my-component')->prop('color', 'green'); 79 | ``` 80 | 81 | Or bind an array that should be passed as **props** to the component: 82 | 83 | ```php 84 | $page->component('my-component')->bind([ 85 | 'title' => 'My Title', 86 | 'color' => 'green' 87 | ]); 88 | ``` 89 | 90 | ## Bind Data 91 | 92 | You may want to bind global data to all views and components contained in the 93 | page. This can be done by passing an array containing the data to the `bind` 94 | method like this: 95 | 96 | ```php 97 | $page->bind($data); 98 | ``` 99 | 100 | The data is now accessible in Blade Views and is passed to Vue components as 101 | props. However, you might want to pass data only to Blade Views or only to Vue 102 | components. You can use `bindToView` and `bindToVue` in that case: 103 | 104 | ```php 105 | $page->bindToView($data); 106 | $page->bindToVue($data); 107 | ``` 108 | 109 | ## Expand 110 | 111 | The container of your Page has a maximum width by default. However, you can 112 | expand the container to the full width. For example, to be able to display large 113 | tables completely. 114 | 115 | ```php 116 | $page->expand(); 117 | ``` 118 | 119 | ## Slots 120 | 121 | On a page there are different **slots** to which elements such as buttons can be 122 | added. These slots are located in two areas: 123 | 124 | - **navigation** - a `sticky` bar on the top of every page 125 | - **header** - contains a title that describes the pages content 126 | 127 | The following screenshot shows the existing slots and where they are located. 128 | 129 | ![navigation](./screens/page_slots.jpg 'navigation') 130 | 131 | Views or Vue components can be added to each slot: 132 | 133 | ```php 134 | $page->navigationLeft()->view('my_button'); 135 | $page->navigationLeft()->component('my-button'); 136 | ``` 137 | 138 | ### Navigation 139 | 140 | Available slots for the **navigation** are: `left`, `right`, `controls` 141 | 142 | ```php 143 | $page->navigationLeft(); 144 | $page->navigationRight(); 145 | $page->navigationControls(); 146 | ``` 147 | 148 | ### Header 149 | 150 | Available slots for the **header** are: `left`, `right` 151 | 152 | ```php 153 | $page->headerLeft(); 154 | $page->headerRight(); 155 | ``` 156 | -------------------------------------------------------------------------------- /basics/screens/navigation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/basics/screens/navigation.jpg -------------------------------------------------------------------------------- /basics/screens/page_slots.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/basics/screens/page_slots.jpg -------------------------------------------------------------------------------- /basics/screens/page_title.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/basics/screens/page_title.jpg -------------------------------------------------------------------------------- /basics/screens/page_view.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/basics/screens/page_view.jpg -------------------------------------------------------------------------------- /charts/area.md: -------------------------------------------------------------------------------- 1 | # Area Chart 2 | 3 | ![Chart Variants](./screens/variants.png) 4 | 5 | An area chart is generated by adding the `--area` flag to the artisan command 6 | `lit:chart {name}`. 7 | 8 | ```shell 9 | php artisan lit:chart SalesProductsChart --area 10 | ``` 11 | 12 | ## Configuration 13 | 14 | Which data is displayed in your chart is configured in the `value` method as 15 | shown below. 16 | 17 | ```php 18 | public function value($query) 19 | { 20 | return $this->count($query); 21 | } 22 | ``` 23 | 24 | Possible methods: 25 | 26 | ```php 27 | return $this->count($query); 28 | return $this->average($query, 'price'); 29 | return $this->min($query, 'price'); 30 | return $this->max($query, 'price'); 31 | return $this->sum($query, 'price'); 32 | ``` 33 | -------------------------------------------------------------------------------- /charts/bar.md: -------------------------------------------------------------------------------- 1 | # Bar Chart 2 | 3 |
4 | drawing 5 |
6 | 7 | A bar chart is generated by adding the `--bar` flag to the artisan command 8 | `lit:chart {name}`. 9 | 10 | ```shell 11 | php artisan lit:chart SalesProductsChart --bar 12 | ``` 13 | 14 | ## Configuration 15 | 16 | Which data is displayed in your chart is configured in the `value` method as 17 | shown below. 18 | 19 | ```php 20 | public function value($query) 21 | { 22 | return $this->count($query); 23 | } 24 | ``` 25 | 26 | Possible methods: 27 | 28 | ```php 29 | return $this->count($query); 30 | return $this->average($query, 'price'); 31 | return $this->min($query, 'price'); 32 | return $this->max($query, 'price'); 33 | return $this->sum($query, 'price'); 34 | ``` 35 | -------------------------------------------------------------------------------- /charts/basics.md: -------------------------------------------------------------------------------- 1 | # Charts 2 | 3 | ## Introduction 4 | 5 | Charts can be used to visualize model data and give the user an overview of 6 | whats going on in his application in a selected time period. Charts can be 7 | displayed on dashboards, index pages as well as on crud detail pages. 8 | 9 | ## Create via Artisan 10 | 11 | Each chart has its own config file. The artisan command `lit:chart {name}` 12 | generates the chart config into `./lit/app/Config/Charts`. 13 | 14 | ```shell 15 | php artisan lit:chart SalesCountChart --area 16 | ``` 17 | 18 | When no type is given as a flag the default chart type `area` will be generated. 19 | 20 | ```shell 21 | php artisan lit:chart MyChart --area 22 | # Creates an area chart. 23 | 24 | php artisan lit:chart MyChart --bar 25 | # Creates a bar chart. 26 | 27 | php artisan lit:chart MyChart --donut 28 | # Creates a donut chart. 29 | 30 | php artisan lit:chart MyChart --number 31 | # Creates a number chart. 32 | 33 | php artisan lit:chart MyChart --progress 34 | # Creates a progress chart. 35 | ``` 36 | 37 | The command `lit:chart` creates a chart config in `./lit/app/Config/Charts`. 38 | 39 | With the `--model` option you can directly specify the name of the model: 40 | 41 | ```shell 42 | php artisan lit:chart MyChart --model=Booking 43 | ``` 44 | 45 | ## Configure 46 | 47 | Next your chart needs to be configured. Every chart type needs its corresponding 48 | Model class and a title. 49 | 50 | ```php 51 | use App\Models\Sale; 52 | 53 | public $model = Sale::class; 54 | 55 | public function title() 56 | { 57 | return 'Sales Count'; 58 | } 59 | ``` 60 | 61 | Additionally, each chart type needs a specific configuration, which are linked 62 | below: 63 | 64 | - [Area Chart](area.md) 65 | - [Bar Chart](bar.md) 66 | - [Donut Chart](donut.md) 67 | - [Number Chart](number.md) 68 | - [Progress](progress.md) 69 | 70 | ### Display Relationship Data 71 | 72 | In some cases you may want to display the data of relations on a detail page of 73 | a crud model. To do so, you need to specify the name of the relation for the 74 | model in the relation property. 75 | 76 | Let's assume that you want to display the number of bookings related to a user 77 | and have created an **area** chart with the name `UserBookingsChart`. The config 78 | for this would look as follows: 79 | 80 | With the `--relation` flag the **property** is placed in the class when 81 | generating the chart config. 82 | 83 | ```shell 84 | php artisan lit:chart UserBookingsChart --model=User --relation=bookings 85 | ``` 86 | 87 | ```php{lit/app/Config/Charts/UserBookingsChart.php} 88 | count($query); 109 | } 110 | } 111 | ``` 112 | 113 | ## Register Charts 114 | 115 | Charts can be registered on pages that extend the `Ignite\Page\Page` class. For 116 | example: `CrudShow` and `CrudIndex`. 117 | 118 | ```php 119 | use Lit\Config\Charts\SalesCountChart; 120 | 121 | $page->chart(SalesCountChart::class); 122 | ``` 123 | 124 | :::tip 125 | 126 | Use a [form](../crud/forms.md) as a dashboard by only displaying charts on it. 127 | 128 | ::: 129 | 130 | ### Customize Card 131 | 132 | Each chart is displayed in a card. You may customize them to your needs. 133 | 134 | #### Variant 135 | 136 | You may display the card in 3 different variants: `primary`, `secondary`, 137 | `white` 138 | 139 | ```php 140 | use Lit\Config\Charts\SalesCountChart; 141 | 142 | $container->chart(SalesCountChart::class)->variant('primary'); 143 | $container->chart(SalesCountChart::class)->variant('secondary'); 144 | $container->chart(SalesCountChart::class)->variant('white'); 145 | ``` 146 | 147 | ![Chart Variants](./screens/variants.png) 148 | 149 | #### Width 150 | 151 | The width of the chart is indicated by `width`. 152 | 153 | ```php 154 | use Lit\Config\Charts\SalesCountChart; 155 | 156 | $container->chart(SalesCountChart::class)->width(1 / 3); 157 | ``` 158 | 159 | #### Height 160 | 161 | The height of the chart is indicated by `height`. 162 | 163 | ```php 164 | use Lit\Config\Charts\SalesCountChart; 165 | 166 | $container->chart(SalesCountChart::class)->height('100px'); 167 | ``` 168 | 169 | ## Number Formatting 170 | 171 | In the `mount` method the chart can be configured. You can set **format**, 172 | **prefixes**, **suffixes** and **currencies**. 173 | 174 | ```php 175 | public function mount(Chart $chart) 176 | { 177 | $chart->format('0,0')->prefix('$ ')->suffix(' cm'); 178 | 179 | // The currency method adds the needed format and suffix: 180 | $chart->currency('€'); 181 | } 182 | ``` 183 | -------------------------------------------------------------------------------- /charts/donut.md: -------------------------------------------------------------------------------- 1 | # DonutChart 2 | 3 |
4 | Donut Chart 5 |
6 | 7 | A donut chart is generated by adding the `--donut` flag to the artisan command 8 | `lit:chart {name}`. 9 | 10 | ```shell 11 | php artisan lit:chart SalesProductsChart --donut 12 | ``` 13 | 14 | ## Configuration 15 | 16 | Which data is displayed in your chart is configured in the `value` method as 17 | shown below. Unlike other chart types, an array with the desired data must be 18 | returned. 19 | 20 | ```php 21 | public function value($query) 22 | { 23 | return [ 24 | $this->count((clone $query)->where('product', 't-shirt')), 25 | $this->count((clone $query)->where('product', 't-shirt')), 26 | ]; 27 | } 28 | ``` 29 | 30 | Possible methods: 31 | 32 | ```php 33 | return $this->count($query); 34 | return $this->average($query, 'price'); 35 | return $this->min($query, 'price'); 36 | return $this->max($query, 'price'); 37 | return $this->sum($query, 'price'); 38 | ``` 39 | 40 | For each array item that is returned in the value method, a label must be 41 | specified in the `labels` method: 42 | 43 | ```php 44 | public function labels(): array 45 | { 46 | return [ 47 | 'T-shirt', 48 | 'Jacket', 49 | ]; 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /charts/number.md: -------------------------------------------------------------------------------- 1 | # Number Chart 2 | 3 |
4 | Number Chart 5 |
6 | 7 | A number chart is generated by adding the `--number` flag to the artisan command 8 | `lit:chart {name}`. 9 | 10 | ```shell 11 | php artisan lit:chart SalesProductsChart --number 12 | ``` 13 | 14 | ## Configuration 15 | 16 | Which data is displayed in your chart is configured in the `value` method as 17 | shown below. 18 | 19 | ```php 20 | public function value($query) 21 | { 22 | return $this->count($query); 23 | } 24 | ``` 25 | 26 | Possible methods: 27 | 28 | ```php 29 | return $this->count($query); 30 | return $this->average($query, 'price'); 31 | return $this->min($query, 'price'); 32 | return $this->max($query, 'price'); 33 | return $this->sum($query, 'price'); 34 | ``` 35 | -------------------------------------------------------------------------------- /charts/progress.md: -------------------------------------------------------------------------------- 1 | # Progress Chart 2 | 3 |
4 | Progress Chart 5 |
6 | 7 | A progress chart is generated by adding the `--progress` flag to the artisan 8 | command `lit:chart {name}`. 9 | 10 | ```shell 11 | php artisan lit:chart SalesProgressChart --progress 12 | ``` 13 | 14 | ## Configuration 15 | 16 | Which data is displayed in your chart is configured in the `value` method as 17 | shown below. 18 | 19 | ```php 20 | public function value($query) 21 | { 22 | return $this->count($query); 23 | } 24 | ``` 25 | 26 | Possible methods: 27 | 28 | ```php 29 | return $this->count($query); 30 | return $this->average($query, 'price'); 31 | return $this->min($query, 'price'); 32 | return $this->max($query, 'price'); 33 | return $this->sum($query, 'price'); 34 | ``` 35 | -------------------------------------------------------------------------------- /charts/screens/bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/charts/screens/bar.png -------------------------------------------------------------------------------- /charts/screens/donut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/charts/screens/donut.png -------------------------------------------------------------------------------- /charts/screens/number.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/charts/screens/number.png -------------------------------------------------------------------------------- /charts/screens/progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/charts/screens/progress.png -------------------------------------------------------------------------------- /charts/screens/variants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/charts/screens/variants.png -------------------------------------------------------------------------------- /configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | ## Introduction 4 | 5 | A configuration file can be found in the laravel config directory 6 | `config/lit.php`. 7 | 8 | ## Basics 9 | 10 | In the following some basic configurations for the admin backend are explained. 11 | All specific configurations are explained in the corresponding documentation. 12 | 13 | Basic configuration keys: 14 | 15 | - `route_prefix` Backend route prefix. 16 | - `default_route` Redirect after login. `route_prefix` is already prepended. 17 | - `login.username` Allow logging in using username or email. 18 | - `translatable` Controls the multilingualism of the admin interface. 19 | 20 | ## Styles And Scripts 21 | 22 | Styles and Scripts can easily be added to your the application: 23 | 24 | ```php 25 | use Ignite\Support\Facades\Lit; 26 | 27 | Lit::style('path/to/your/style.css'); 28 | Lit::script('path/to/your/script.js'); 29 | ``` 30 | -------------------------------------------------------------------------------- /crud/actions.md: -------------------------------------------------------------------------------- 1 | # Actions 2 | 3 | ## Introduction 4 | 5 | Actions are a convenient feature to create reusable tasks for models. Each 6 | action can be placed in different locations. For example in your index table or 7 | on a detail page of a model. 8 | 9 | ## Create 10 | 11 | Create an action via artisan: 12 | 13 | ```shell 14 | php artisan lit:action MyAction 15 | ``` 16 | 17 | The created actions are located in `./lit/app/Actions`. 18 | 19 | ```php 20 | namespace Lit\Actions; 21 | 22 | use Illuminate\Support\Collection; 23 | 24 | class MyAction 25 | { 26 | public function run(Collection $models) 27 | { 28 | // Do Something. 29 | } 30 | } 31 | ``` 32 | 33 | ## Responses 34 | 35 | When a `message` is returned via a json response, a toast is displayed in the 36 | lower right corner of the page containing the message. This can be displayed in 37 | four variants: `success`, `info`, `warning`, `danger`. The default is `success`. 38 | 39 | ```php 40 | public function run(Collection $models) 41 | { 42 | return response()->json(['message' => 'Hello there!', 'variant' => 'info']); 43 | } 44 | ``` 45 | 46 | There is a helper for each variant: 47 | 48 | ```php 49 | return response()->success('My message.'); 50 | return response()->info('My message.'); 51 | return response()->warning('My message.'); 52 | return response()->danger('My message.'); 53 | ``` 54 | 55 |
56 | message success 57 | message info 58 | message warning 59 | message danger 60 |
61 | 62 | ### Redirects 63 | 64 | In some cases you may want to redirect the user to another page after the action 65 | has been executed. This can be done as usual by returning a 66 | [redirect](https://laravel.com/docs/7.x/redirects). 67 | 68 | ```php 69 | public function run(Collection $models) 70 | { 71 | // Do Something. 72 | 73 | return redirect('your/redirect/url'); 74 | } 75 | ``` 76 | 77 | ## Confirm Modal 78 | 79 | If your action has the function modal, the execution of the action must be 80 | confirmed via a modal. 81 | 82 | ```php 83 | namespace Lit\Actions; 84 | 85 | use Illuminate\Support\Collection; 86 | use Ignite\Page\Actions\ActionModal; 87 | 88 | class MyAction 89 | { 90 | public function modal(ActionModal $modal) 91 | { 92 | $modal->confirmVariant('primary') 93 | ->confirmText('Run') 94 | ->message('Do you want to run the Action?'); 95 | } 96 | 97 | public function run(Collection $models) 98 | { 99 | // Do Something. 100 | } 101 | } 102 | ``` 103 | 104 | ## Fields 105 | 106 | Form fields can be added to the confirm modal of an action. The values of these 107 | fields are passed to the action. This allows you, for example, to let the user 108 | type in a message to be sent by mail, as shown the following example. 109 | 110 | ```php 111 | use Illuminate\Support\Collection; 112 | use Ignite\Page\Actions\ActionModal; 113 | use Ignite\Page\Actions\AttributeBag; 114 | 115 | public function modal(ActionModal $modal) 116 | { 117 | $modal->form(function($form) { 118 | $form->text('message')->title('Message'); 119 | }); 120 | } 121 | 122 | public function run(Collection $models, AttributeBag $attributes) 123 | { 124 | foreach($models as $model) { 125 | Mail::to($model)->send(new ExampleEmail($attributes->message)); 126 | } 127 | } 128 | ``` 129 | 130 |
131 | action fields 132 |
133 | 134 | ## Display the Action 135 | 136 | ### In a Table 137 | 138 | There are multiple places where an `action` can be displayed in a table, first 139 | of all an action can be executed for all selected items: 140 | 141 | ```php 142 | // CrudConfig 143 | 144 | use Lit\Actions\MyAction; 145 | 146 | public function index(CrudIndex $page) 147 | { 148 | $page->table(...) 149 | ->action('My Action', MyAction::class); 150 | } 151 | ``` 152 | 153 | Additionally actions can be displayed in table columns to make important actions 154 | more accessible. You can add either one action as a button or several actions as 155 | dropdown to a column: 156 | 157 | ```php 158 | use Lit\Actions\MyAction; 159 | use Lit\Actions\OtherAction; 160 | 161 | $page->table(function($table) { 162 | // Single action as button: 163 | $table->action('My Action', MyAction::class); 164 | 165 | // Multiple actions as dropdown: 166 | $table->actions([ 167 | 'My Action' => MyAction::class, 168 | 'Other Action' => OtherAction::class, 169 | ]); 170 | }); 171 | ``` 172 | 173 | ### On a Page 174 | 175 | Actions can also be displayed on the show page of a crud, even in the slots 176 | `navigationLeft`, `navigationRight`, `navigationControls`, `headerLeft` and 177 | `headerRight`: 178 | 179 | ![navigation](./../basics/screens/page_slots.jpg 'navigation') 180 | 181 | ```php 182 | // CrudConfig 183 | 184 | use Lit\Actions\MyAction; 185 | 186 | public function show(CrudShow $page) 187 | { 188 | $page->navigationLeft()->action('My Action', MyAction::class); 189 | $page->navigationRight()->action('My Action', MyAction::class); 190 | $page->navigationControls()->action('My Action', MyAction::class); 191 | $page->headerLeft()->action('My Action', MyAction::class); 192 | $page->headerRight()->action('My Action', MyAction::class); 193 | } 194 | ``` 195 | 196 | You may even place it somewhere on your page: 197 | 198 | ```php 199 | $page->card(function($page) { 200 | $page->action('My Action', MyAction::class); 201 | }); 202 | ``` 203 | 204 | The `variant` of the actions that are displayed as buttons can be adjusted: 205 | 206 | ```php 207 | $page->headerLeft() 208 | ->action('My Action', MyAction::class) 209 | ->variant('outline-primary'); 210 | ``` 211 | 212 | ## Conditional Actions 213 | 214 | You may want to display actions depending on the value of a model attribute. 215 | This can be achieved by applying any of the existing 216 | [field dependencies](../fields/conditions.md#usage) to your action like this: 217 | 218 | ```php 219 | $page->headerLeft() 220 | ->action('cancel', CancelBookingAction::class) 221 | ->whenNot('state', 'canceled'); 222 | ``` 223 | -------------------------------------------------------------------------------- /crud/forms.md: -------------------------------------------------------------------------------- 1 | # Forms 2 | 3 | ## Introduction 4 | 5 | Forms provide a convenient way to store, organize and maintain data of many 6 | kinds, such as your page content. You may create as many `Forms` as you like. 7 | 8 | Think of a `form` as a model with **dynamic** attributes. Its structure may 9 | change at any time. `Forms` are being managed on a crud-page just like 10 | [crud models](model.md). 11 | 12 | Forms are grouped into form `collections` to keep the overview. For example, the 13 | forms **home** and **faq**, which contain the page content for the pages 14 | **home** and **faq**, could be included in the `collection` **pages**. 15 | 16 | ## Generate Form 17 | 18 | A `form` can be created using the following artisan command: 19 | 20 | ```shell 21 | php artisan lit:form 22 | ``` 23 | 24 | A wizard will take you through all required steps. You may also create the form by adding the **collection** and the **name** as arguments to the artisan command: 25 | 26 | ```php 27 | php artisan lit:form pages home 28 | ``` 29 | 30 | The corresponding `config` 31 | and the `controller` is created afterwards. 32 | 33 | A config file and a controller will be generated. Checkout the [model](model.md) 34 | documentation to learn how to apply **permissions** on forms. 35 | 36 | ## Navigation 37 | 38 | Add the navigation entry by adding the namespace of the newly generated config 39 | to your navigation. 40 | 41 | ```php{lit/app/Config/NavigationConfig.php} 42 | use Lit\Config\Pages\HomeConfig; 43 | 44 | $nav->preset(HomeConfig::class, ['icon' => fa('home')]), 45 | ``` 46 | 47 | ## Configuration 48 | 49 | Define the form config in the created config file: 50 | `Config/Form/{collection}/{form}Config.php`. First the controller must be 51 | specified in the config: 52 | 53 | ```php 54 | use Lit\Controllers\Form\Pages\HomeController; 55 | 56 | /** 57 | * Controller class. 58 | * 59 | * @var string 60 | */ 61 | public $controller = HomeController::class; 62 | ``` 63 | 64 | ### Form Fields 65 | 66 | All form fields for the form are specified in the `show` method: 67 | 68 | ```php 69 | public function show($page) 70 | { 71 | $page->card(function($form) { 72 | $form->input('title'); 73 | }); 74 | } 75 | ``` 76 | 77 | Read the [Crud Show](show.md) documentation to learn more on how to customize 78 | your forms. 79 | 80 | ## Retrieve Data 81 | 82 | In order to retrieve the form data, you have to add the **Form Facade** to your 83 | controller. Data can now be easily retrieved with the `load` function like this: 84 | 85 | ```php 86 | use Ignite\Support\Facades\Form; 87 | 88 | $form = Form::load('pages', 'home'); 89 | ``` 90 | 91 | This allows the data to be passed directly to a 92 | [View](https://laravel.com/docs/7.x/blade#displaying-data). 93 | 94 | ```php 95 | use Ignite\Support\Facades\Form; 96 | 97 | return view('home')->with([ 98 | 'home' => Form::load('pages', 'home') 99 | ]); 100 | ``` 101 | 102 | and be used in a Blade template: 103 | 104 | ```php 105 |

{{ $home->title }}

106 | ``` 107 | 108 | ### Load Using Namespace 109 | 110 | If you want to load the form data of a single config, you can also use the 111 | static load function of the config. This allows you to "click" directly into the 112 | class in your editor. 113 | 114 | ```php 115 | use Lit\Config\Form\Pages\Home; 116 | 117 | $home = HomeConfig::load(); 118 | 119 | echo $home->title; 120 | ``` 121 | 122 | ### Retrieve A Full Collection 123 | 124 | It is also possible to load all data for a collection as shown in the example: 125 | 126 | ```php 127 | use Ignite\Support\Facades\Form; 128 | 129 | $settings = Form::load('settings'); 130 | 131 | echo $settings->main->title; 132 | ``` 133 | -------------------------------------------------------------------------------- /crud/index.md: -------------------------------------------------------------------------------- 1 | # Index Config 2 | 3 | ## Introduction 4 | 5 | Each Crud configuration can have an index page that shows an overview of the 6 | models. This index page is configured in the `index` method of its corresponding 7 | config. 8 | 9 | ```php 10 | use Ignite\Crud\CrudIndex; 11 | 12 | public function index(CrudIndex $page) 13 | { 14 | // Build your index page here. 15 | } 16 | ``` 17 | 18 | `Ignite\Crud\CrudIndex` is an instance of `Ignite\Page\Page` so all functions 19 | described in the [Page](../basics/page.md) documentation can be used. This 20 | includes binding Vue components or Blade views components to a page: 21 | 22 | ```php 23 | $page->component('foo'); // Vue component 24 | $page->view('foo'); // Blade view 25 | ``` 26 | 27 | In the Config for a CRUD model its index table is defined. 28 | 29 | ## Table 30 | 31 | The index table is built using the method `table` like this: 32 | 33 | ```php 34 | use Ignite\Crud\CrudIndex; 35 | 36 | public function index(CrudIndex $page) 37 | { 38 | $page->table(function($table) { 39 | $table->col('Name')->value('{first_name} {last_name}'); 40 | }); 41 | } 42 | ``` 43 | 44 | The [table config](table.md) describes how columns with **images**, 45 | **relations** and much more can be built. 46 | 47 | ## Eager Loading 48 | 49 | Eager loadings can be performed in the `query` method. Here you can modify the 50 | query that is executed when loading the index table items. 51 | 52 | ```php 53 | use Ignite\Crud\CrudIndex; 54 | 55 | public function index(CrudIndex $page) 56 | { 57 | $page->table(...) 58 | ->query(function($query) { 59 | $query->with('department')->withCount('projects_count'); 60 | }); 61 | } 62 | ``` 63 | 64 | ## Search 65 | 66 | All attributes to be searched for are specified in `search`. You can also 67 | specify `relations` and their attributes. 68 | 69 | ```php 70 | use Ignite\Crud\CrudIndex; 71 | 72 | public function index(CrudIndex $page) 73 | { 74 | $page->table(...)->search('title', 'department.name'); 75 | } 76 | ``` 77 | 78 | ## Sort 79 | 80 | You can sort by all model `attributes` as well as `relations` `attributes`. The 81 | sortBy attributes are specified as follows: `{attributes}.{desc|asc}`. The 82 | default attribute to sort by is specified in the `sortByDefault` method. 83 | 84 | ```php 85 | use Ignite\Crud\CrudIndex; 86 | 87 | public function index(CrudIndex $page) 88 | { 89 | $page->table(...)->sortByDefault('id.desc'); 90 | } 91 | ``` 92 | 93 | In this example you can see how the array for the sort attributes can look like 94 | to sort by `id` or by a `relation`. 95 | 96 | ```php 97 | use Ignite\Crud\CrudIndex; 98 | 99 | public function index(CrudIndex $page) 100 | { 101 | $page->table(...) 102 | ->sortBy([ 103 | 'id.desc' => 'New first', 104 | 'id.asc' => 'Old first', 105 | 'department.name.desc' => 'Department A-Z', 106 | 'department.name.asc' => 'Department Z-A' 107 | ]); 108 | } 109 | ``` 110 | 111 | :::tip 112 | 113 | In case of long loading times when sorted by relation attributes it can help to 114 | add an [index](https://laravel.com/docs/7.x/migrations#indexes) on the column 115 | that connects the relation. 116 | 117 | ::: 118 | 119 | ## Filter 120 | 121 | Filters are specified in groups. Laravel's model 122 | [`scopes`](https://laravel.com/docs/7.x/eloquent#local-scopes) are used to 123 | filter the index table as shown in the example: 124 | 125 | ```php{lit/app/Config/PostConfig.php} 126 | use Ignite\Crud\CrudIndex; 127 | 128 | public function index(CrudIndex $page) 129 | { 130 | $page->table(...) 131 | ->filter([ 132 | 'Department' => [ 133 | 'development' => 'Development', 134 | 'marketing' => 'Marketing', 135 | ], 136 | ]); 137 | } 138 | ``` 139 | 140 | ```php{app/Models/Post.php} 141 | public function scopeDevelopment() 142 | { 143 | return $this->hasOne('App\Models\Department')->where('name', 'development'); 144 | } 145 | 146 | public function scopeMarketing() 147 | { 148 | return $this->hasOne('App\Models\Department')->where('name', 'marketing'); 149 | } 150 | ``` 151 | 152 | ### Default Filter 153 | 154 | You may also specify one or more default filter that will be used after the page 155 | is loaded: 156 | 157 | ```php{lit/app/Config/PostConfig.php} 158 | $page->table(...) 159 | ->defaultFilter('development') 160 | ->filter([ 161 | 'Department' => [ 162 | 'development' => 'Development', 163 | 'marketing' => 'Marketing', 164 | ], 165 | ]); 166 | ``` 167 | 168 | ### Custom Filter With Form Fields 169 | 170 | To add filters with form fields like e.g. `checkboxes` or `date` pickers you can 171 | create custom filters. A filter is generated via the artisan command 172 | `lit:filter`: 173 | 174 | ```shell 175 | php artisan lit:filter MyCustomFilter 176 | ``` 177 | 178 | The following class will the be generated: 179 | 180 | ```php{lit/app/Filters/MyCustomFilter.php} 181 | 182 | namespace Lit\Filters; 183 | 184 | use Ignite\Crud\Filter\Filter; 185 | use Ignite\Crud\Filter\FilterForm; 186 | use Ignite\Support\AttributeBag; 187 | use Illuminate\Database\Eloquent\Builder; 188 | 189 | class MyCustomFilter extends Filter 190 | { 191 | /** 192 | * Apply field attributes to query. 193 | * 194 | * @param Builder $query 195 | * @param AttributeBag $attributes 196 | * @var void 197 | */ 198 | public function apply($query, AttributeBag $attributes) 199 | { 200 | // 201 | } 202 | 203 | /** 204 | * Add filter form fields. 205 | * 206 | * @param FilterForm $form 207 | * @return void 208 | */ 209 | public function form(FilterForm $form) 210 | { 211 | // 212 | } 213 | } 214 | ``` 215 | 216 | #### Add Form Fields 217 | 218 | You can now add fields like this: 219 | 220 | ```php 221 | public function form(FilterForm $form) 222 | { 223 | $form->datetime('from'); 224 | $form->datetime('to'); 225 | } 226 | ``` 227 | 228 | Or Checkboxes: 229 | 230 | ```php 231 | use App\Models\Tag; 232 | 233 | public function form(FilterForm $form) 234 | { 235 | $options = Tag::all()->pluck('name')->toArray(); 236 | 237 | $form->checkboxes('tags')->options($options); 238 | } 239 | ``` 240 | 241 | #### Apply Field Attributes To The Query 242 | 243 | The next thing you want to do is to apply the field attributes to the query: 244 | 245 | ```php 246 | public function apply($query, AttributeBag $attributes) 247 | { 248 | if ($attributes->from) { 249 | $query->where('created_at', '>=', $attributes->from); 250 | } 251 | 252 | if ($attributes->to) { 253 | $query->where('created_at', '<', $attributes->to); 254 | } 255 | } 256 | ``` 257 | 258 | #### Use Custom Filter 259 | 260 | The custom Filter can now be used for your CRUD index: 261 | 262 | ```php{lit/app/Config/PostConfig.php} 263 | use Lit\Filters\MyCustomFilter; 264 | 265 | $page->table(...) 266 | ->filter([ 267 | 'Button Text' => MyCustomFilter::class, 268 | ]); 269 | ``` 270 | 271 | ## Pagination 272 | 273 | The maximum number of items to be displayed on a page is defined in `perPage`. 274 | The default is `10`. 275 | 276 | ```php 277 | use Ignite\Crud\CrudIndex; 278 | 279 | public function index(CrudIndex $page) 280 | { 281 | $page->table(...)->perPage(5); 282 | } 283 | ``` 284 | -------------------------------------------------------------------------------- /crud/model.md: -------------------------------------------------------------------------------- 1 | # Models 2 | 3 | ## Introduction 4 | 5 | The main task of an admin panel is to manage data. Litstack offers easy editing 6 | and managing of 7 | [Laravel Eloquent Models](https://laravel.com/docs/7.x/eloquent). It lets you 8 | attach a variety of **form fields** to model attributes. There are **relation 9 | fields** that to link any available models in any laravel relation, and the 10 | ability to attach fields to attributes from pivot tables. 11 | 12 | The administrative views of a model include two views. An index view with a 13 | table and a detail view in which information for a single model can be displayed 14 | or edited. These are configured in litstack in the so-called configs. The 15 | `./lit/app/Config/Crud` directory contains all configuration files for your 16 | CRUD-Models. Each model may have one or more config files. 17 | 18 | ::: tip 19 | 20 | Configurations can be created for existing Models. 21 | 22 | ::: 23 | 24 | Litstack also uses the following Open-Source packages to extend the 25 | functionality of Models: 26 | 27 | - [Astronomic Translatable](https://docs.astrotomic.info/laravel-translatable/) 28 | Used for Model translations. 29 | - [Spatie Medialibrary](https://docs.spatie.be/laravel-medialibrary/v8/introduction/) 30 | Used for media management. 31 | - [Cviebrock Sluggable](https://github.com/cviebrock/eloquent-sluggable) Used 32 | to apply slugs to model attributes. 33 | 34 | ## Generate Config 35 | 36 | Assuming you want to generate a crud-config for the Model with the name `Post`, 37 | you can simply generate a crud-config for the model using the `lit:crud` 38 | command. 39 | 40 | ```shell 41 | php artisan lit:crud Post 42 | ``` 43 | 44 | Executing the command will create all necessary files, unless they already 45 | exist: 46 | 47 | - The migration for the `posts` Table 48 | - The model `App\Models\Post` 49 | - The config `./lit/app/Config/Crud/PostConfig` 50 | - The controller `./lit/app/Http/Controllers/Crud/PostController` 51 | 52 | Now the config can be added to the navigation so it can be reached via your 53 | admin panel. 54 | 55 | ```php{lit/app/Config/NavigationConfig.php} 56 | use Lit\Config\Crud\PostConfig; 57 | 58 | $nav->preset(PostConfig::class, ['icon' => fa('newspaper')]), 59 | ``` 60 | 61 | ### Config Name 62 | 63 | Since you are able to create **multiple** configurations for the same model, in 64 | some cases you may want to use a config name that does not begin with the class 65 | name of the model. The name of the config can be given as the second argument to 66 | the `lit:crud` command: 67 | 68 | ```shell 69 | php artisan lit:crud User StargazerConfig 70 | ``` 71 | 72 | ## Media 73 | 74 | If your model should have media like pictures or pdfs, it needs to implement the 75 | `Spatie\MediaLibrary\HasMedia` **interface** and use the **trait** 76 | `Ignite\Crud\Models\Traits\HasMedia`, as shown in the following example: 77 | 78 | ```php{app/Models/Post.php} 79 | namespace App\Models; 80 | 81 | use Ignite\Crud\Models\Traits\HasMedia; 82 | use Illuminate\Database\Eloquent\Model; 83 | use Spatie\MediaLibrary\HasMedia as HasMediaContract; 84 | 85 | class Test extends Model implements HasMediaContract 86 | { 87 | use HasMedia; 88 | 89 | // ... 90 | } 91 | ``` 92 | 93 | Litstack generates the a Model with the needed requirements by adding the 94 | `--media` (or short `-m`) options to the `lit:crud` command: 95 | 96 | ```shell 97 | php artisan lit:crud Post -m 98 | ``` 99 | 100 | Now you can add images to your model via the [image field](../fields/image.md). 101 | 102 | ## Translatable 103 | 104 | The litstack form fields make managing translatable content easier than ever: 105 | 106 | ```php 107 | $form->input('title')->translatable(); 108 | ``` 109 | 110 | To use translatable fields in models the correct configuration is required, 111 | which is done from within the **migration** and the **model**, as described 112 | below. 113 | 114 | ::: tip 115 | 116 | The required configuration is generated automatically by adding the 117 | `--translatable` (or short `-t`) option to the `lit:crud` command. 118 | 119 | ::: 120 | 121 | ### Migration 122 | 123 | In the migration a second table must be created, which contains the translatable 124 | fields. For `posts` this would be `post_translations`. All required **columns** 125 | can be added to the translations table by using `translates` with the name of 126 | the table to be translated. In the following example the column title is 127 | translatable for the posts table. 128 | 129 | ```php{database/migrations/*create_posts_table.php} 130 | Schema::create('posts', function (Blueprint $table) { 131 | $table->bigIncrements('id'); 132 | $table->timestamps(); 133 | }); 134 | Schema::create('post_translations', function (Blueprint $table) { 135 | $table->translates('posts'); 136 | $table->string('title'); 137 | }); 138 | ``` 139 | 140 | ### Model 141 | 142 | Your translation model, in our case post, needs the **interface** 143 | `Astrotomic\Translatable\Contracts\Translatable` and the **trait** 144 | `Ignite\Crud\Models\Traits\Translatable`. Furthermore, all translatable 145 | attributes are specified in the `translatedAttributes` property. 146 | 147 | ```php{app/Models/Post.php} 148 | setLocale('en'); 218 | echo $post->title; // Echo's english value. 219 | 220 | app()->setLocale('de'); 221 | echo $post->title; // Echo's german value. 222 | ``` 223 | 224 | ::: tip 225 | 226 | Read more about translatable models in the 227 | [package documentation](https://docs.astrotomic.info/laravel-translatable/). 228 | 229 | ::: 230 | 231 | ## Sluggable 232 | 233 | Models that should have one or more slugs need the trait 234 | `Ignite\Crud\Models\Traits\Sluggable`. The trait is automatically added to the 235 | mode when it is created by the command `lit:crud` with the option `--slug` 236 | (short `-s`): 237 | 238 | ```shell 239 | php artisan lit:crud Post -s 240 | ``` 241 | 242 | The `sluggable` method of the model specifies which attributes contain slugs and 243 | from which attributes the slugs are built. In the following example the column 244 | `slug` contains the slug that is built from the value of `title`. 245 | 246 | ```php 247 | namespace App\Models; 248 | 249 | use Ignite\Crud\Models\Traits\Sluggable; 250 | use Illuminate\Database\Eloquent\Model; 251 | 252 | class Post extends Model 253 | { 254 | use Sluggable; 255 | 256 | protected $fillable = ['title']; 257 | 258 | public function sluggable(): array 259 | { 260 | return [ 261 | 'slug' => [ 262 | 'source' => 'title', 263 | ], 264 | ]; 265 | } 266 | } 267 | ``` 268 | 269 | ::: tip 270 | 271 | Read more about the sluggable options in the 272 | [package documentation](https://github.com/cviebrock/eloquent-sluggable). 273 | 274 | ::: 275 | 276 | ::: warning 277 | 278 | Make sure the **Sluggable** trait and configuration are in the correct Model 279 | when using **translatable** Models. 280 | 281 | ::: 282 | 283 | ## Fill Model On Create & Update 284 | 285 | You may want fill attributes to the model before it gets created or updated from 286 | the user via a crud form. This can be achieved by modifying the Model in either 287 | `fillOnStore` or `fillOnUpdate` the crud controller. 288 | 289 | The following example show's how to assign an author to a post by setting the 290 | `author_id` to the authenticated litstack user id. 291 | 292 | ```php{lit/app/Http/Controllers/Crud/PostController.php} 293 | namespace Lit\Http\Controllers\Crud; 294 | 295 | use Ignite\Crud\Controllers\CrudController; 296 | use Lit\Models\User; 297 | 298 | class PostController extends CrudController 299 | { 300 | public function fillOnStore($post) 301 | { 302 | $post->author_id = lit_user()->id; 303 | } 304 | 305 | public function fillOnUpdate($post) 306 | { 307 | // ... 308 | } 309 | } 310 | ``` 311 | 312 | ## Permissions 313 | 314 | Litstack brings not only a super simple **permission manager**, but also a 315 | simple way to create permissions and bind them to crud models. The desired 316 | permissions just need to be added to the migration `*_make_permissions.php` and 317 | will be added to the database by executing the `lit:permissions` command. 318 | 319 | ### Create Permissions 320 | 321 | So let's create crud permissions for our posts example. So we add `posts` to the 322 | `crudPermissionGroups` property. This will create the following permissions: 323 | 324 | - `create posts` 325 | - `read posts` 326 | - `update posts` 327 | - `delete posts` 328 | 329 | ```php{database/migrations/______________________make_permissions.php} 330 | protected $crudPermissionGroups = [ 331 | // ... 332 | 333 | 'posts' 334 | ]; 335 | ``` 336 | 337 | and execute the command: 338 | 339 | ```shell 340 | php artisan lit:permissions 341 | ``` 342 | 343 | ### Apply Permissions 344 | 345 | The controller that comes with the crud contains the authorize method. The 346 | second parameter is the operation to be executed. So now we can check if the 347 | authenticated user has the permission to operate on the group `posts` by 348 | returning `$user->can("{$operation} posts")`: 349 | 350 | ```php{lit/app/Http/Controllers/Crud/PostController.php} 351 | can("{$operation} posts"); 372 | } 373 | } 374 | ``` 375 | 376 | ### Authorize individual Models 377 | 378 | You may want to authorize individual models. This can be achieved by adding the 379 | initial query in the `query` method. The following example shows how models can 380 | be hidden by users who did not create them: 381 | 382 | ```php{lit/app/Http/Controllers/Crud/PostController.php} 383 | class PostController 384 | { 385 | public function query($query) 386 | { 387 | $query->where('created_by', lit_user()->id); 388 | } 389 | } 390 | ``` 391 | 392 | ## Navigation 393 | 394 | Add the navigation entry by adding the config namespace preset to your 395 | navigation. 396 | 397 | ```php 398 | $nav->preset(PostConfig::class, ['icon' => fa('newspaper')]), 399 | ``` 400 | 401 | ## Configuration 402 | 403 | Define the CRUD-Config in the created config file: 404 | `Config/Crud/{model}Config.php`. First the model and the controller must be 405 | specified in the config: 406 | 407 | ```php 408 | use App\Models\Article; 409 | use Lit\Controllers\Crud\ArticleController; 410 | use Ignite\Crud\Config\CrudConfig; 411 | 412 | class ArticleConfig extends CrudConfig 413 | { 414 | /** 415 | * Model class. 416 | * 417 | * @var string 418 | */ 419 | public $model = Article::class; 420 | 421 | /** 422 | * Controller class. 423 | * 424 | * @var string 425 | */ 426 | public $controller = ArticleController::class; 427 | } 428 | ``` 429 | 430 | ### Index Table, Create & Update Form 431 | 432 | Next, the configuration for the [Index Table](index.md) and the **create** and 433 | **update** [Form](show.md) can be adjusted. 434 | -------------------------------------------------------------------------------- /crud/screens/action_modal_fields.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/crud/screens/action_modal_fields.png -------------------------------------------------------------------------------- /crud/screens/message_danger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/crud/screens/message_danger.png -------------------------------------------------------------------------------- /crud/screens/message_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/crud/screens/message_info.png -------------------------------------------------------------------------------- /crud/screens/message_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/crud/screens/message_success.png -------------------------------------------------------------------------------- /crud/screens/message_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/crud/screens/message_warning.png -------------------------------------------------------------------------------- /crud/screens/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/crud/screens/preview.gif -------------------------------------------------------------------------------- /crud/screens/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/crud/screens/search.png -------------------------------------------------------------------------------- /crud/search.md: -------------------------------------------------------------------------------- 1 | # Search 2 | 3 | You can make models searchable and allow your user to quickly find what they are 4 | looking for. 5 | 6 | ![search](./screens/search.png 'search') 7 | 8 | ## Setup 9 | 10 | First you need to enable the search by adding the 11 | `Ignite\Search\SearchServiceProvider` service provider to you `lit` config: 12 | 13 | ```php 14 | // ... 15 | 16 | 'providers' => [ 17 | // ... 18 | \Ignite\Search\SearchServiceProvider::class, 19 | ] 20 | ``` 21 | 22 | Now you choose the crud's that should be searchable and edit the displayed 23 | search result by adding the `searchResult` method to the associated crud config: 24 | 25 | ```php 26 | use App\Models\Order; 27 | use Ignite\Search\Result; 28 | 29 | class OrderConfig extends CrudConfig 30 | { 31 | // ... 32 | 33 | public function searchResult(Result $result, Order $order) 34 | { 35 | $result 36 | ->title("Order #{$order->id}") 37 | ->description($order->products()->count().' Products.') 38 | ->hint("Created By {$order->user->name}") 39 | ->icon(fa('shopping-cart')); 40 | } 41 | } 42 | ``` 43 | 44 | And finally register the crud config to your search in the created 45 | `SearchConfig`: 46 | 47 | ```php{lit/app/Config/SearchConfig.php} 48 | public function main(Search $search) 49 | { 50 | $search 51 | ->add(OrderConfig::class) 52 | ->add(CustomerConfig::class); 53 | } 54 | ``` 55 | 56 | ## Image Preview 57 | 58 | To add an image preview you may pass the image to the search result: 59 | 60 | ```php 61 | public function searchResult(Result $result, User $user) 62 | { 63 | $result 64 | ->title($user->name) 65 | ->description($user->email) 66 | ->image($user->profile_image); 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /crud/show.md: -------------------------------------------------------------------------------- 1 | # Show Config 2 | 3 | ## Introduction 4 | 5 | In the `show` method of a **Form** or a **CRUD** config all components and 6 | fields are configured for editing the data. 7 | 8 | ```php 9 | use Ignite\Crud\CrudShow; 10 | 11 | public function show(CrudShow $page) 12 | { 13 | // Define the page here. 14 | } 15 | ``` 16 | 17 | `Ignite\Crud\CrudShow` is an instance of `Ignite\Page\Page` so all functions 18 | described in the [Page](../basics/page.md) documentation can be used. This 19 | includes binding Vue components or Blade views to a page: 20 | 21 | ```php 22 | $page->component('foo'); // Vue component 23 | $page->view('foo'); // Blade view 24 | ``` 25 | 26 | ## Card 27 | 28 | Form fields must be grouped into `cards`. You are free to create only one or any 29 | number of cards for a form. 30 | 31 | ```php 32 | use Ignite\Crud\CrudShow; 33 | 34 | public function show(CrudShow $page) 35 | { 36 | $page->card(function ($form) { 37 | 38 | // Build your form in here. 39 | 40 | $form->input('first_name')->title('First Name'); 41 | 42 | }); 43 | } 44 | ``` 45 | 46 | All available fields can be found in the documentation under 47 | [Fields](../fields/introduction.md). 48 | 49 | ### Customize Card 50 | 51 | You may customize your card with the following options: 52 | 53 | | Method | Description | 54 | | --------------------- | ------------------------------------------------------------------- | 55 | | `$card->title('Foo')` | The title description for the card. | 56 | | `$card->width(1/2)` | Width of the card. | 57 | | `$card->secondary()` | Gives your card a secondary background, for less important content | 58 | 59 | ## Group 60 | 61 | With `group` fields can be grouped in a column. This is useful to organize form 62 | elements of different heights side by side. 63 | 64 | ```php 65 | $form->group(function($form) { 66 | // Build your form inside the col. 67 | })->width(6); 68 | ``` 69 | 70 | ## Info 71 | 72 | A good content administration interface includes **descriptions** that help the 73 | user to quickly understand what is happening on the interface. Such information 74 | can be created outside and inside of cards like this: 75 | 76 | ```php 77 | use Ignite\Crud\CrudShow; 78 | 79 | public function show(CrudShow $page) 80 | { 81 | $page->info('Address') 82 | ->width(4) 83 | ->text('This address appears on your invoices.') 84 | ->text(...); 85 | 86 | // ... 87 | } 88 | ``` 89 | 90 | ## Preview 91 | 92 | ![preview](./screens/preview.gif 'preview') 93 | 94 | You may want to provide a direct **preview** of the crud's associated page. This 95 | can be done using the `preview` method in your crud or form like this: 96 | 97 | ```php 98 | use Ignite\Crud\CrudShow; 99 | 100 | public function show(CrudShow $page) 101 | { 102 | $page->preview(function($post = null, $locale) { 103 | return route('posts.show', [ 104 | 'slug' => $post->slug ?? '' 105 | ]); 106 | }); 107 | } 108 | ``` 109 | 110 | You may even provide a route for every language, so the user gets a preview for 111 | all languages: 112 | 113 | ```php 114 | $page->preview(function($post = null, $locale) { 115 | return route($locale.'.posts.show', [ 116 | 'slug' => $post->translate($locale)->slug ?? '' 117 | ]); 118 | }); 119 | ``` 120 | 121 | ### Default Device 122 | 123 | The default device can be changed in the config `lit.php` under 124 | 'crud.preview.default_device'. 125 | 126 | ```php 127 | 'crud' => [ 128 | 'preview' => [ 129 | // Available devices: mobile, tablet, desktop 130 | 'default_device' => 'desktop' 131 | ] 132 | ], 133 | ``` 134 | -------------------------------------------------------------------------------- /crud/table.md: -------------------------------------------------------------------------------- 1 | # Table 2 | 3 | ## Introduction 4 | 5 | `tables` can be easily configured in the backend. You can easily display 6 | attributes, relationships or include your own `Vue` components to adjust the 7 | table as needed. The following explains how to customize the tables to your 8 | needs. 9 | 10 | ## Column Value 11 | 12 | ### Text 13 | 14 | Casual text columns are added with the function `col($label)`. Attached are all 15 | methods for configuring the column. 16 | 17 | ```php 18 | $table->col('Name'); 19 | ``` 20 | 21 | The `value` of the column is indicated by the function value. You can specify 22 | model attributes in curly brackets to include them in the text flow. 23 | 24 | ```php 25 | $table->col('Name')->value('{first_name} {last_name}'); 26 | ``` 27 | 28 | #### Display Relationship Attributes 29 | 30 | It is also possible to display the attribute of relationships. In this case 31 | attributes must be separated with a dot like this: 32 | 33 | ```php 34 | $table->col('Product')->value('{product.name}'); 35 | ``` 36 | 37 | #### Display Options 38 | 39 | Maybe you want to display a value representative for a state, this can be 40 | achieved by passing the attribute name as the first and an array of options as 41 | the second parameter to the value method: 42 | 43 | ```php 44 | use App\Models\Product; 45 | 46 | $table->col('State')->value('state', [ 47 | Product::AVAILABLE => 'available', 48 | Product::OUT_OF_STOCK => 'out of stock', 49 | ]); 50 | ``` 51 | 52 | ### Text Alignment 53 | 54 | You may set the text align to right like shown in the following examples: 55 | 56 | ```php 57 | $table->col('amount')->value('{amount} €')->right(); 58 | $table->col('state')->value('{state}')->center(); 59 | ``` 60 | 61 | ### Strip Html 62 | 63 | For example, if you want to display the value of a `wysiwyg` field, it makes 64 | sense to strip the **html tags** and specify a maximum number of characters like 65 | this: 66 | 67 | ```php 68 | $table->col('Text') 69 | ->value('{text}') 70 | ->stripHtml() 71 | ->maxChars(50); 72 | ``` 73 | 74 | ### Regex 75 | 76 | Perform a regular expression search and replace: 77 | 78 | ```php 79 | $table->col('Fruit') 80 | ->value('orange') 81 | ->regex('/\b(\w*orange\w*)\b/im', 'apple'); // Replaces orange with apple. 82 | ``` 83 | 84 | ### Money 85 | 86 | Let's assume that you want to display an amount of money in a column. For this 87 | the `money` method with the desired attribute can be used. The amount is 88 | formatted and the column can be sorted by the attribute. 89 | 90 | ```php 91 | $table->money('amount'); 92 | ``` 93 | 94 | #### Currency 95 | 96 | For formatting the 97 | [formatCurrency](https://www.php.net/manual/de/numberformatter.formatcurrency.php) 98 | method of the PHP 99 | [NumberFormatter](https://www.php.net/manual/de/class.numberformatter.php) is 100 | used. This makes it possible to choose the 3-letter ISO 4217 currency code. The 101 | default currency code is `EUR`. 102 | 103 | ```php 104 | $table->money('amount', 'USD'); 105 | ``` 106 | 107 | Additionally, the language can be specified as a third parameter. However, the 108 | locale of the authenticated user is used by default. 109 | 110 | ```php 111 | $table->money('amount', 'USD', 'en_US'); 112 | ``` 113 | 114 | Useful **ISO 4217** codes: 115 | 116 | | Code | Currency | Example (`de_DE`) | 117 | | ------- | ----------------- | ----------------- | 118 | | `"EUR"` | Euro | `"10,00 €"` | 119 | | `"USD"` | US Dollar | `"10,00 $"` | 120 | | `"AUD"` | Australian Dollar | `"10,00 AU$"` | 121 | | `"CHF"` | Swiss Franc | `"10,00 CHF"` | 122 | | `"GGP"` | Pound | `"10,00 £"` | 123 | 124 | ### Date 125 | 126 | To display a formatted date, you may use the `date` method. A parameter with the 127 | desired formatting is required. 128 | 129 | ```php 130 | $table->date('created_at', 'Y-m-d'); 131 | ``` 132 | 133 | ## Reduce Width 134 | 135 | With the function `small` the column is reduced to the minimum width. 136 | 137 | ```php 138 | $table->col('Icon')->value('{icon}')->small(); 139 | ``` 140 | 141 | ## Sortable 142 | 143 | A table column can be sorted directly by clicking on the column in the table 144 | head. To achieve this, you simply have to specify the name of the attribute you 145 | want to sort by. 146 | 147 | ```php 148 | $table->col('Name')->value('{first_name} {last_name}')->sortBy('first_name'); 149 | ``` 150 | 151 | You may even sort by related column. 152 | 153 | ```php 154 | $table->col('Product')->value('{product.name}')->sortBy('product.name'); 155 | ``` 156 | 157 | :::tip 158 | 159 | In case of long loading times when sorted by relation attributes it can help to 160 | add an [index](https://laravel.com/docs/7.x/migrations#indexes) on the column 161 | that connects the relation. 162 | 163 | ::: 164 | 165 | ## Form Fields 166 | 167 | In litstack form fields can be placed in table columns, this allows the user to 168 | edit attributes directly in the table similar to excel. Each column can contain 169 | only one form field. 170 | 171 | ```php 172 | $table->field('Name')->input('{name}'); 173 | ``` 174 | 175 | If you want to modify the 176 | 177 | ## Action 178 | 179 | You may make [actions](actions.md) available directly in a table column: 180 | 181 | ```php 182 | use Lit\Actions\SendMailAction; 183 | 184 | $table->action('Send Mail', SendMailAction::class)->label('Mail'); 185 | ``` 186 | 187 | ::: tip 188 | 189 | Use conditions to only show actions for certain models: 190 | 191 | ```php 192 | $table->action('Cancel', CancelBookingAction::class) 193 | ->whenNot('state', 'canceled'); 194 | ``` 195 | 196 | ::: 197 | 198 | ### Multiple Actions 199 | 200 | You can also place multiple actions in one column. These are then accessible via 201 | a dropdown button 202 | 203 | ```php 204 | use Lit\Actions\FooAction; 205 | use Lit\Actions\BarAction; 206 | 207 | $table->actions([ 208 | 'Foo' => FooAction::class, 209 | 'Bar' => BarAction::class, 210 | ])->label('Actions'); 211 | ``` 212 | 213 | ## Image 214 | 215 | If an image is to be displayed in a table, the image url must also be specified 216 | using the `src` method. If the image was uploaded via the `Image` Field, the 217 | conversions specified in the config file **lit.php** can be displayed. 218 | 219 | ```php 220 | $table->image('Image')->src('{image.url}'); 221 | ``` 222 | 223 | ::: tip 224 | 225 | Display **media conversion** for images that where uploaded via the `Image` 226 | field. 227 | 228 | Example: `$column->src('{image.conversion_urls.sm}')` 229 | 230 | ::: 231 | 232 | ### Avatar 233 | 234 | You may use avatar to display a rounded image. 235 | 236 | ```php 237 | $table->avatar('Image')->src('{image.conversion_urls.sm}'); 238 | ``` 239 | 240 | ### maxWidth, maxHeight 241 | 242 | Furthermore, a `maxWidth` and a `maxHeight` can be defined. 243 | 244 | ```php 245 | $table->image('Image') 246 | ->src('{image.conversion_urls.sm}') 247 | ->maxWidth('50px') 248 | ->maxHeight('50px'); 249 | ``` 250 | 251 | ### Square 252 | 253 | Set a width and a height if the image should simply be displayed as a square: 254 | 255 | ```php 256 | $table->image('Image') 257 | ->src('{image.conversion_urls.sm}') 258 | ->square('50px'); // Displays the image as 50 x 50 px square using object-fit: cover 259 | ``` 260 | 261 | ## Progress 262 | 263 | Often you want to display the progress of a model directly in a table column. 264 | Litstack provides the progress column for this purpose: 265 | 266 | ```php 267 | $table->progress('value', $max = 100)->label('Progress'); 268 | ``` 269 | 270 | ## Relation 271 | 272 | In some cases, you may want to link a relation directly in your table. This can 273 | be achieved by using the `relation` method. The related `name` of the relation 274 | and the related crud config must be specified. 275 | 276 | ```php 277 | use Ignite\Support\Facades\Config; 278 | use Lit\Config\Crud\ProductConfig; 279 | 280 | $table->relation('product', ProductConfig::class) 281 | ->value('{product.name}') // Related attribute to be displayed. 282 | ->sortBy('product.name'); 283 | ``` 284 | 285 | ### MorphTo 286 | 287 | I case your relationship is of the type 288 | [MorphTo](https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-polymorphic-model-structure), 289 | you need to apply the config classes and values for all models like this: 290 | 291 | ```php 292 | use App\Models\Post; 293 | use App\Models\Video; 294 | use Lit\Config\Crud\PostConfig; 295 | use Lit\Config\Crud\VideoConfig; 296 | 297 | $table->relation('commentable', [ 298 | Post::class => PostConfig::class, 299 | Video::class => VideoConfig::class, 300 | ])->value([ 301 | Post::class => '{commentable.title}', 302 | Video::class => '{commentable.title}', 303 | ]); 304 | ``` 305 | 306 | ## Toggle 307 | 308 | To edit the boolean state of a model directly in a table, a **switch** can be 309 | displayed in a column using `toggle`. The name of the corresponding attribute 310 | must be specified as the first parameter. In addition, the `routePrefix` for the 311 | update route must be specified, if the table is built in a CRUD or form config, 312 | simply use the config function `routePrefix`. 313 | 314 | ```php 315 | $table->toggle('active') 316 | ->label('Live') 317 | ->sortBy('active'); 318 | ``` 319 | 320 | ::: warning 321 | 322 | Please use an inline `boolean` form field instead of the toggle column since it 323 | might be dropped in **4.x**. 324 | 325 | ```php 326 | $table->field('Live', fn($column) => $column->sortBy('active')) 327 | ->boolean('active'); 328 | ``` 329 | 330 | ::: 331 | 332 | ## Blade View 333 | 334 | With the `view` method you can easily add Blade Views to your table column: 335 | 336 | ```php 337 | $table->view('lit::columns.hello')->label('Hello'); 338 | ``` 339 | 340 | ```html{lit/resources/views/columns/hello.blade.php} 341 |
342 | Hello World! 343 |
344 | ``` 345 | 346 | ### Vue in Blade components 347 | 348 | You can use Vue components in your blade component: 349 | 350 | ```html{lit/resources/views/columns/hello.blade.php} 351 | 352 | Hello World! 353 | 354 | ``` 355 | 356 | Use the **prop** `item` to display model attributes: 357 | 358 | ```html{lit/resources/views/columns/hello.blade.php} 359 | 360 | ``` 361 | 362 | ## Vue Component 363 | 364 | You can also integrate your own Vue components into columns. The component 365 | **name** is specified as the first parameter, the label must be specified 366 | separately. Additionally props can be defined. 367 | 368 | ```php 369 | $table->component('my-table-component') 370 | ->label('State') 371 | ->prop('variants' => [ 372 | 'active' => 'success', 373 | 'complete' => 'primary', 374 | 'failed' => 'danger' 375 | ]) 376 | ->sortBy('state'); 377 | ``` 378 | 379 | Your component could look like this: 380 | 381 | ```javascript 382 | 387 | 402 | ``` 403 | 404 | Read the [Extend Vue](../basics/vue.md#bootstrap-vue) section to learn how to 405 | register your own Vue components. 406 | -------------------------------------------------------------------------------- /fields/block.md: -------------------------------------------------------------------------------- 1 | # Block 2 | 3 | ## Introduction 4 | 5 | Block fields are used to map repetitive content. They can contain any number of 6 | so called **repeatables**, which you can string together in any order. A 7 | **repeatable** can be regarded as a separate individual form. As well a preview 8 | table can be set for every block. If field values are to be displayed as 9 | preview, they must be written in **curly brackets**. 10 | 11 | ```php 12 | $form->block('content') 13 | ->title('Content') 14 | ->repeatables(function($repeatables) { 15 | 16 | // Add as many repeatables as you want. 17 | $repeatables->add('text', function($form, $preview) { 18 | // The block preview. 19 | $preview->col('{text}'); 20 | 21 | // Containing as many form fields as you want. 22 | $form->input('text') 23 | ->title('Text'); 24 | }); 25 | 26 | $repeatables->add('image', function($form, $preview) { 27 | $preview->col('{}'); 28 | 29 | $form->image('image') 30 | ->title('Image'); 31 | }); 32 | }); 33 | ``` 34 | 35 | ### Preparing the Model 36 | 37 | Block fields can be added to CRUD-Models as well as to forms. Blocks don't need 38 | a dedicated column in the model, as they are stored in a database table 39 | centrally. 40 | 41 | The repeatables can be loaded to your model using the `repeatables` **relation** 42 | method. 43 | 44 | ```php 45 | public function content() 46 | { 47 | return $this->repeatables('content'); 48 | } 49 | ``` 50 | 51 | You can now receive the block data like this: 52 | 53 | ```php 54 | Post::find($id)->content; 55 | ``` 56 | 57 | ## Binding Views 58 | 59 | You can directly bind a view to a repeatable to use it in the frontend where you 60 | display your block: 61 | 62 | ```php{3} 63 | $repeatables->add('text', function($form, $preview) { 64 | // ... 65 | })->view('repeatables.text'); 66 | ``` 67 | 68 | You may even bind Blade x components using the `x` method: 69 | 70 | ```php{3} 71 | $repeatables->add('text', function($form, $preview) { 72 | // ... 73 | })->x('repeatables.text'); 74 | ``` 75 | 76 | ## Reusable Repeatables 77 | 78 | Sometimes you want to use repeatables in different places. Reusable repeatables 79 | can be created using the `lit:repeatable` command. The **preview** and **form** 80 | can then be configured in the newly generated class in the `lit/app/Repeatables` 81 | directory. 82 | 83 | ```shell 84 | php artisan lit:repeatable text 85 | ``` 86 | 87 | The generated class can be added to a block by passing the **namespace** as the 88 | first parameter to the `add` method: 89 | 90 | ```php 91 | use Lit\Repeatables\TextRepeatable; 92 | 93 | $repeatables->add(TextRepeatable::class); 94 | ``` 95 | 96 | ## Frontend 97 | 98 | To use the repeatables of a block in the frontend you can loop over them and 99 | display the content depending on the repeatable `type`, like this: 100 | 101 | ```php 102 | @foreach($model->content as $repeatable) 103 | @if($repeatable->type == 'text') 104 | {{ $repeatable->text }} 105 | @elseif($repeatable->type == 'image') 106 | {{-- ... --}} 107 | @endif 108 | @endforeach 109 | ``` 110 | 111 | However you can simply use the blade directive `block`, which does exactly that 112 | for you. 113 | 114 | ```php 115 | @block($model->content) 116 | ``` 117 | 118 | ::: warning 119 | 120 | The `block` directive needs a View or a Blade x component bound to the 121 | repeatable in order to be displayed. 122 | 123 | ::: 124 | 125 | ## Methods 126 | 127 | | Method | Description | 128 | | ----------------------- | -------------------------------------------------- | 129 | | `$field->title()` | The title description for this field. | 130 | | `$field->repeatables()` | A closure where all repeatable blocks are defined. | 131 | | `$field->width()` | Width of the field. | 132 | | `$field->blockWidth()` | Width of a block. | 133 | 134 | ## Repeatable Methods 135 | 136 | | Method | Description | 137 | | ----------------------- | ------------------------------------------------ | 138 | | `$repeatable->button()` | The title for the repeatable. | 139 | | `$repeatable->view()` | The View describing the repeatable. | 140 | | `$repeatable->x()` | The Blade x component describing the repeatable. | 141 | -------------------------------------------------------------------------------- /fields/boolean.md: -------------------------------------------------------------------------------- 1 | # Boolean 2 | 3 | ## Usage 4 | 5 | The boolean field adds a switch to a boolean attribute. 6 | 7 | ```php 8 | $form->boolean('active') 9 | ->title('Live') 10 | ->hint('Put the site online.') 11 | ->width(1/3); 12 | ``` 13 | 14 | Add the `boolean` 15 | [cast](https://laravel.com/docs/5.2/eloquent-mutators#attribute-casting) to your 16 | model: 17 | 18 | ```php 19 | protected $casts = [ 20 | 'active' => 'boolean' 21 | ]; 22 | ``` 23 | 24 | ## Methods 25 | 26 | | Method | Description | 27 | | ----------------------------------- | ------------------------------------------------------------------ | 28 | | `$field->title('Live')` | The title description for this field. | 29 | | `$field->hint('Foo.')` | A short hint that should describe how to use the field. | 30 | | `$field->info('...')` | Question mark with tooltip. (Can contain longer field descriptions) | 31 | | `$field->width(1/2)` | Width of the field. | 32 | | `$field->rules('required')` | Rules that should be applied when **updating** and **creating**. | 33 | | `$field->creationRules('required')` | Rules that should be applied when **creating**. | 34 | | `$field->updateRules('required')` | Rules that should be applied when **updating**. | 35 | -------------------------------------------------------------------------------- /fields/checkboxes.md: -------------------------------------------------------------------------------- 1 | # Checkboxes 2 | 3 | ## Introduction 4 | 5 | Multiple checkboxes. The selected values are stored as an array. 6 | 7 | ## Usage 8 | 9 | The following example shows a list of fruits that can be selected using 10 | checkboxes. 11 | 12 | ```php 13 | $form->checkboxes('fruits') 14 | ->title('Fruits') 15 | ->options([ 16 | 'orange' => 'Orange', 17 | 'apple' => 'Apple', 18 | 'pineapple' => 'Pineapple', 19 | 'grape' => 'Grape', 20 | ]) 21 | ->hint('Select your fruits.') 22 | ->width(6); 23 | ``` 24 | 25 | ### Cast 26 | 27 | Add the `array` 28 | [cast](https://laravel.com/docs/5.2/eloquent-mutators#attribute-casting) to your 29 | model: 30 | 31 | ```php 32 | protected $casts = [ 33 | 'fruits' => 'array' 34 | ]; 35 | ``` 36 | 37 | ## Methods 38 | 39 | | Method | Description | 40 | | ----------------------------------- | ---------------------------------------------------------------------- | 41 | | `$field->title('Foo')` | The title description for this field. | 42 | | `$field->hint('Foo.')` | A short hint that should describe how to use the field.` | 43 | | `$field->info('...')` | Question mark with tooltip. (Can contain longer field descriptions) | 44 | | `$field->width(1/2)` | Width of the field. | 45 | | `$field->options(['foo', 'bar'])` | An array with checkbox values and descriptions. | 46 | | `$field->stacked()` | Places each checkbox one over the other instead of next to each other. | 47 | | `$field->rules('required')` | Rules that should be applied when **updating** and **creating**. | 48 | | `$field->creationRules('required')` | Rules that should be applied when **creating**. | 49 | | `$field->updateRules('required')` | Rules that should be applied when **updating**. | 50 | -------------------------------------------------------------------------------- /fields/conditions.md: -------------------------------------------------------------------------------- 1 | # Conditional Fields 2 | 3 | ## Introduction 4 | 5 | Field **conditions** can be used to display fields when a model attribute has a 6 | certain value. Individual fields or field groups can be made dependent on model 7 | values. 8 | 9 | ![radio conditions](./screens/conditions/conditions_radio.gif 'radio conditions') 10 | 11 | ## Usage 12 | 13 | The following example shows an input field that only gets displayed if model 14 | attribute `type` has the value `news`: 15 | 16 | ```php 17 | $form->select('type') 18 | ->options([ 19 | 'news' => 'News', 20 | 'blog' => 'Blog', 21 | ]) 22 | ->title('Type'); 23 | 24 | $form->input('news_title') 25 | ->title('Title') 26 | ->when('type, 'news'); 27 | ``` 28 | 29 | A variety of conditions are available for any field: 30 | 31 | | Condition | Description | 32 | | ------------------------------------------- | ------------------------------------------- | 33 | | `$field->when('type', 'foo')` | Matches the exact given value. | 34 | | `$field->whenNot('type', 'foo')` | When field doesn't match the given value. | 35 | | `$field->whenContains('type', 'foo')` | Matches the given substring or array value. | 36 | | `$field->whenNotContains('type', 'foo')` | When field doesn't contain the given value. | 37 | | `$field->whenIn('type', ['foo', 'bar'])` | When field is any of the given values. | 38 | | `$field->whenNotIn('type', ['foo', 'bar'])` | When field is not any of the given values. | 39 | 40 | ### Conditional Groups 41 | 42 | Conditions can also be applied to groups: 43 | 44 | ```php{4} 45 | $form->group(function($form) { 46 | 47 | $form->input('news_title')->title('Title'); 48 | $form->input('news_text')->title('Text'); 49 | 50 | })->when('type', 'news'); 51 | ``` 52 | 53 | ### Multiple Conditions 54 | 55 | You may chain as many conditions in a row by adding `or` to the desired 56 | condition: 57 | 58 | ```php 59 | $form->input('title')->title('Title') 60 | ->when($field, 'news') 61 | ->orWhen($field, 'blog'); 62 | ``` 63 | -------------------------------------------------------------------------------- /fields/date-time.md: -------------------------------------------------------------------------------- 1 | # DateTime 2 | 3 | ## Introduction 4 | 5 | A DateTime-Picker. 6 | 7 |
8 | 9 |
10 | 11 | ## Examples 12 | 13 | The following example shows the basic usage of the `datetime` field. 14 | 15 | ```php 16 | $form->datetime('publish_at') 17 | ->title('Date') 18 | ->formatted('l') 19 | ->hint('Chose a date.') 20 | ->width(6); 21 | ``` 22 | 23 | ### Shortcut 24 | 25 | ```php 26 | $form->dt('publish_at') // dt and datetime work the same 27 | ``` 28 | 29 | ### Date and Time 30 | 31 | You may enable to pick a time as well by settings `onlyDate` to false: 32 | 33 | ```php{3} 34 | $form->datetime('publish_at') 35 | ->title('Date') 36 | ->onlyDate(false) 37 | ->formatted('l') 38 | ->hint('Chose a date.') 39 | ->width(6); 40 | ``` 41 | 42 |
43 | 44 |
45 | 46 | ## Methods 47 | 48 | | Method | Description | 49 | | ----------------------------------- | ---------------------------------------------------------------- | 50 | | `$field->title('Publish At')` | The title description for this field. | 51 | | `$field->formatted('LL')` | The shown datetime format. (Useful formats listed below.) | 52 | | `$field->hint('Pick a date.')` | A closure where all repeatable blocks are defined. | 53 | | `$field->onlyDate()` | Pick date only (default: `true`). | 54 | | `$field->onlyTime()` | Pick time only (default: `false`). | 55 | | `$field->minuteInterval(15)` | Timepicker minute interval (default: `5`). | 56 | | `$field->width(1/2)` | Width of the field. | 57 | | `$field->rules('required')` | Rules that should be applied when **updating** and **creating**. | 58 | | `$field->creationRules('required')` | Rules that should be applied when **creating**. | 59 | | `$field->updateRules('required')` | Rules that should be applied when **updating**. | 60 | 61 | ## Formats 62 | 63 | Useful formats: 64 | 65 | | Key | Example Result | 66 | | ------ | -------------------------------- | 67 | | `LT` | 2:15 PM | 68 | | `LTS` | 2:15:52 PM | 69 | | `L` | 12/08/2019 | 70 | | `l` | 12/8/2019 | 71 | | `LL` | December 8, 2019 | 72 | | `ll` | Dec 8, 2019 | 73 | | `LLL` | December 8, 2019 2:15 PM | 74 | | `lll` | Dec 8, 2019 2:15 PM | 75 | | `LLLL` | Sunday, December 8, 2019 2:15 PM | 76 | | `llll` | Sun, Dec 8, 2019 2:15 PM | 77 | -------------------------------------------------------------------------------- /fields/icon.md: -------------------------------------------------------------------------------- 1 | # Icon 2 | 3 | An icon picker field. 4 | 5 | ```php 6 | $form->icon('icon') 7 | ->title('Icon') 8 | ->icons([ 9 | '', 10 | '', 11 | // ... 12 | ]) 13 | ->hint('Choose your icon.') 14 | ->width(2); 15 | ``` 16 | 17 | If the number of icons is high, it is recommended to `require` the icons from a 18 | file. 19 | 20 | ```php 21 | ->icon(require('.../icons.php')); 22 | ``` 23 | 24 | ## Add Your Own Icons 25 | 26 | To import your own icons you have to specify the corresponding `css` file in the 27 | config `lit.php`. 28 | 29 | ```php 30 | 'assets' => [ 31 | // ... 32 | 'css' => [ 33 | '/icons/icons.css', // Add your icon's css file. 34 | // ... 35 | ], 36 | ], 37 | ``` 38 | 39 | ## Methods 40 | 41 | | Method | Description | 42 | | -------------------------------------------- | --------------------------------------------------------------------------- | 43 | | `$field->title('Foo')` | The title description for this field. | 44 | | `$field->hint('Foo.')` | A short hint that should describe how to use the field. | 45 | | `$field->info('...')` | Question mark with tooltip. (Can contain longer field descriptions) | 46 | | `$field->width(1/2)` | Width of the field. | 47 | | `$field->icons([''])` | List of selectable icons. (By default all fontawesome icons are selectable) | 48 | | `$field->rules('required')` | Rules that should be applied when **updating** and **creating**. | 49 | | `$field->creationRules('required')` | Rules that should be applied when **creating**. | 50 | | `$field->updateRules('required')` | Rules that should be applied when **updating**. | 51 | -------------------------------------------------------------------------------- /fields/image.md: -------------------------------------------------------------------------------- 1 | # Image 2 | 3 | ## Introduction 4 | 5 | A drag and drop image uploader using Spatie's 6 | [medialibary](https://docs.spatie.be/laravel-medialibrary/v7/introduction/). 7 | 8 | ## Model Setup 9 | 10 | To attach images to a model, only the media **contract** and the media **trait** 11 | must be added to the model. 12 | 13 | ```php 14 | use Ignite\Crud\Models\Traits\HasMedia; 15 | use Spatie\MediaLibrary\HasMedia as HasMediaContract; 16 | 17 | class Post extends Model implements HasMediaContract 18 | { 19 | use HasMedia; 20 | } 21 | ``` 22 | 23 | ## Basics 24 | 25 | For all images that are uploaded an input field for `alt` and `title` is 26 | displayed, with `translatable` these two fields are made translatable. 27 | 28 | ```php 29 | $form->image('images') // images is the corresponding media collection. 30 | ->translatable() 31 | ->title('Images') 32 | ->hint('Image Collection.') 33 | ->maxFiles(5); 34 | ``` 35 | 36 | Add the image attribute to your model: 37 | 38 | ```php 39 | public function getImagesAttribute() 40 | { 41 | return $this->getMedia('images'); 42 | } 43 | ``` 44 | 45 | ## Crop 46 | 47 | To crop the image to a desired ratio before uploading it, a ratio can be defined 48 | using the method `crop`. 49 | 50 | ```php{3} 51 | $form->image('images')->title('Images')->crop(16 / 9); 52 | ``` 53 | 54 | ::: tip 55 | 56 | If no ratio is passed as a parameter to the crop method, the image can be freely 57 | cropped. 58 | 59 | ::: 60 | 61 | ## Expand 62 | 63 | By default the images are displayed as a square. However, this view is not 64 | suitable for example for header images. With **expand** you can display the 65 | image at full size. 66 | 67 | ```php{2} 68 | $form->image('header_image')->title('Header Image')->expand(); 69 | ``` 70 | 71 | ![Image expand](./screens/image/expand.png 'Image expand') 72 | 73 | ## Preview Image 74 | 75 | In the case that the first image from the list should be used as a preview 76 | image, you can use `firstBig` to display the first image bigger to show that it 77 | has a special importance. 78 | 79 | ```php{3} 80 | $form->image('images') 81 | ->title('Images') 82 | ->firstBig() 83 | ->hint('The first image is the preview image.'); 84 | ``` 85 | 86 | ![Image firstBig](./screens/image/first_big.png 'Image firstBig') 87 | 88 | ## Conversions 89 | 90 | In the config `lit.mediaconversions` all conversions groups are specified. If 91 | you would like a model to use another conversion group than `default`, the group 92 | name can be set using the attribute `mediaconversions`. 93 | 94 | ```php 95 | class Post extends Model implements HasMediaContract 96 | { 97 | ... 98 | 99 | /** 100 | * Media conversions group. 101 | * 102 | * @var string 103 | */ 104 | protected $mediaconversions = 'other'; 105 | } 106 | ``` 107 | 108 | ::: warning 109 | 110 | To display conversion urls it is important to set the env `APP_URL` to the url 111 | you are working in. 112 | 113 | ::: 114 | 115 | ## Max. File Size 116 | 117 | The maximum allowed file size for an image can be specified using the 118 | `maxFileSize` method. The file size is given in **megabytes**. The default value 119 | is 12 mb. 120 | 121 | ```php{3} 122 | $form->image('images')->title('Images')->maxFileSize(25); 123 | ``` 124 | 125 | ## Methods 126 | 127 | | Method | Description | 128 | | -------------------------- | ------------------------------------------------------------------ | 129 | | `$field->title('Image')` | The title for this form field. | 130 | | `$field->translatable()` | Should the field be translatable. | 131 | | `$field->hint('Foo.')` | A short hint that should describe how to use the form field.` | 132 | | `$field->info('...')` | Question mark with tooltip. (Can contain longer field descriptions) | 133 | | `$field->width(1/2)` | Width of the form field. | 134 | | `$field->sortable()` | Should the images be sortable? (default: `true`) | 135 | | `$field->maxFiles(1)` | Maximum number of uploadable images. (default: `5`) | 136 | | `$field->maxFileSize(100)` | Maximum file size. (default: `12`) | 137 | | `$field->expand()` | Expand the preview image to its full width. | 138 | | `$field->crop(16/9)` | Opens a Crop-Tool before the upload. (default: `false`) | 139 | | `$field->showFullImage()` | Display's the full image inside of the square box. | 140 | | `$field->firstBig()` | Display's the first image bigger. | 141 | -------------------------------------------------------------------------------- /fields/input.md: -------------------------------------------------------------------------------- 1 | # Input 2 | 3 | A basic text input field. 4 | 5 | ```php 6 | $form->input('title') 7 | ->title('Title') 8 | ->placeholder('Title') 9 | ->hint('The Title is shown at the top of the page.') 10 | ->width(1/2); 11 | ``` 12 | 13 | ## Prepend & Append 14 | 15 | For units or similar, values can be appended or prepended to the input field. 16 | 17 | ```php 18 | $form->input('length') 19 | ->title('Length') 20 | ->type('number') 21 | ->placeholder('The length in cm') 22 | ->hint('Enter the length in cm.') 23 | ->append('cm') 24 | ->width(12); 25 | ``` 26 | 27 | ## Methods 28 | 29 | | Method | Description | 30 | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 31 | | `$field->title()` | The title description for this form field. | 32 | | `$field->placeholder()` | The placeholder for this form field. | 33 | | `$field->type()` | Sets an input type for the input. [Available types](https://bootstrap-vue.js.org/docs/components/form-input#input-type): **text**, **number**, **email**, **password**, **search**, **url**, **tel**, **date**, **time**, **range**, **color** | 34 | | `$field->hint()` | A short hint that should describe how to use the form field. | 35 | | `$field->info('...')` | Question mark with tooltip. (Can contain longer field descriptions) | 36 | | `$field->width()` | Width of the field. | 37 | | `$field->translatable()` | Should the form field be translatable? For translatable crud models, the translatable fields are automatically recognized. | 38 | | `$field->max()` | Max characters. | 39 | | `$field->prepend()` | Prepend the field. | 40 | | `$field->append()` | Append the field. | 41 | | `$field->rules()` | Rules that should be applied when **updating** and **creating**. | 42 | | `$field->creationRules()` | Rules that should be applied when **creating**. | 43 | | `$field->updateRules()` | Rules that should be applied when **updating**. | 44 | -------------------------------------------------------------------------------- /fields/introduction.md: -------------------------------------------------------------------------------- 1 | # Fields 2 | 3 | ## Introduction 4 | 5 | Fields can be used to make database entries easily editable. Each field is 6 | appended one or more columns of a database table. 7 | [Validation Rules](https://laravel.com/docs/8.x/validation) can be added to 8 | fields and it can be determined who can edit a field. 9 | 10 | ## Basics 11 | 12 | When you create a field you must first specify the `attribute` that the field 13 | refers to. Like in the following example an input field refers to `first_name`. 14 | 15 | ```php 16 | $form->input('first_name'); 17 | ``` 18 | 19 | Every field requires a title. 20 | 21 | ```php 22 | $form->input('first_name')->title('Firstname'); 23 | ``` 24 | 25 | Furthermore the width can be specified either in **12** columns as in bootstrap, 26 | or in fractions. The fractions are converted into columns. 27 | 28 | ```php 29 | $form->input('first_name')->title('Firstname')->width(4); 30 | // Is the same as: 31 | $form->input('first_name')->title('Firstname')->width(1 / 3); 32 | ``` 33 | 34 | ## Authorization 35 | 36 | With the `authorize` method it can be determined if the user has the permission 37 | for a field. If the user does not have the required authorization, the field is 38 | not displayed. 39 | 40 | ```php 41 | $form->input('first_name')->authorize(function($user) { 42 | return $user->can('edit user-name'); 43 | }); 44 | ``` 45 | 46 | ## Readonly 47 | 48 | If you want the user to see the field, but not be able to edit it, you can use 49 | the `readOnly` function. 50 | 51 | ```php 52 | $form->input('first_name')->readOnly(! lit_user()->can('edit user-name')); 53 | ``` 54 | -------------------------------------------------------------------------------- /fields/list.md: -------------------------------------------------------------------------------- 1 | # List 2 | 3 | ## Introduction 4 | 5 | A list field with nested items. It can be used to build **navigations** with 6 | nested entries. 7 | 8 | ```php 9 | $form->list('menue') 10 | ->title('Menue') 11 | ->previewTitle('{title}') 12 | ->form(function($form) { 13 | $form->input('title') 14 | ->title('Title'); 15 | }); 16 | ``` 17 | 18 | :::tip 19 | 20 | Add creation **rules** to the fields of your list to prevent the creation of 21 | empty items 22 | 23 | ::: 24 | 25 | ### Preparing the Model 26 | 27 | List fields can be added to CRUD-Models as well as to forms. Lists don't need a 28 | dedicated column in the model, as they are stored in a database table centrally. 29 | 30 | ```php 31 | public function menue() 32 | { 33 | return $this->listItems('menue'); 34 | } 35 | ``` 36 | 37 | You can now receive the list items like this: 38 | 39 | ```php 40 | Post::find($id)->menue; 41 | ``` 42 | 43 | ## Max Depth 44 | 45 | The maximum depth of the list levels can be specified with `maxDepth`. The 46 | default value is `3`. 47 | 48 | ```php{3} 49 | $form->list('menue') 50 | ->title('Menue') 51 | ->maxDepth(4) 52 | ->previewTitle('{title}') 53 | ->form(function($form) { 54 | $form->input('title') 55 | ->title('Title'); 56 | }); 57 | ``` 58 | 59 | ## Retrieve Data 60 | 61 | ## Methods 62 | 63 | | Method | Description | 64 | | ----------------------- | ------------------------------------------ | 65 | | `$field->title()` | The title description for this form field. | 66 | | `$field->form()` | The corresponding form to the list item. | 67 | | `$field->previewTitle()`| Title that describes the form. | 68 | | `$field->maxDepth()` | Title that describes the form. | 69 | -------------------------------------------------------------------------------- /fields/masks.md: -------------------------------------------------------------------------------- 1 | # Field Masks 2 | 3 | ## Introduction 4 | 5 | Apply input masks to your field to indicate the format of valid input values. 6 | Litstack makes use of [Cleave.js](https://nosir.github.io/cleave.js/) to apply 7 | masks to form fields. 8 | 9 | ## Basic Usage 10 | 11 | To add masks to your form field you may specify the desired mask options by 12 | passing an array to the `mask` method of your field: 13 | 14 | ```php 15 | $form->input('credit_card')->mask([ 16 | 'creditCard': true 17 | ]); 18 | ``` 19 | 20 | Checkout some useful masks on 21 | [nosir.github.io/cleave.js](https://nosir.github.io/cleave.js/). 22 | 23 | ## Add Addons 24 | 25 | To make use of cleave js addons like phone number masks of your country, you 26 | need to add the script of the desired addon to your `lit` config so it will be 27 | loaded. 28 | 29 | ```php{config/lit.php} 30 | 'assets' => [ 31 | // ... 32 | 'scripts' => [ 33 | // ... 34 | // Add us phone number. 35 | 'https://cdnjs.cloudflare.com/ajax/libs/cleave.js/1.6.0/addons/cleave-phone.us.js' 36 | ], 37 | ] 38 | ``` 39 | 40 | The US phone number mask can now be applied like this: 41 | 42 | ```php 43 | $form->input('phone_number')->mask([ 44 | 'phone' => true, 45 | 'phoneRegionCode' => 'us', 46 | ]); 47 | ``` 48 | 49 | ## Conditional Options 50 | 51 | You may use attribute values to add conditional options by adding the attribute 52 | in curly brackets: 53 | 54 | ```php 55 | $form->select('country')->options([ 56 | 'de' => 'de', 57 | 'us' => 'us', 58 | ]); 59 | 60 | $form->input('title')->mask([ 61 | 'phone' => true, 62 | 'phoneRegionCode' => '{country}', 63 | ]); 64 | ``` 65 | -------------------------------------------------------------------------------- /fields/modal.md: -------------------------------------------------------------------------------- 1 | # Modal 2 | 3 | Form fields inside a `modal`. 4 | 5 | ```php 6 | $form->modal('update_email') 7 | ->title('E-Mail') 8 | ->name('Update E-Mail') 9 | ->form(function($form) { 10 | $form->input('email')->title('E-Mail'); 11 | }); 12 | ``` 13 | 14 | ## Confirm with Password 15 | 16 | Appends a password field to the end of the form that is required to confirm the 17 | modal form using the current users password. 18 | 19 | ```php{4} 20 | $form->modal('update_email') 21 | ->title('E-Mail') 22 | ->name('Update E-Mail') 23 | ->confirmWithPassword() 24 | ->form(function($form) { 25 | $form->input('email')->title('E-Mail'); 26 | }); 27 | ``` 28 | 29 | ## Methods 30 | 31 | | Method | Description | 32 | | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | 33 | | `$field->title()` | The title description for this field. | 34 | | `$field->placeholder()` | The placeholder for this field. | 35 | | `$field->hint()` | A short hint that should describe how to use the field.` | 36 | | `$field->info()` | Question mark with tooltip. (Can contain longer field descriptions) | 37 | | `$field->width()` | Width of the field. | 38 | | `$field->confirmWithPassword()` | Appends a password field to the end of the form that is required to confirm the modal form using the current users password. | 39 | -------------------------------------------------------------------------------- /fields/password.md: -------------------------------------------------------------------------------- 1 | # Password 2 | 3 | ## Introduction 4 | 5 | A `password` input Field. 6 | 7 | ```php 8 | $form->password('password') 9 | ->title('Password'); 10 | ``` 11 | 12 | ## Confirm Form 13 | 14 | Update or create form requires a password confirmation. 15 | 16 | ```php{3} 17 | $form->password('password') 18 | ->title('Password') 19 | ->confirm(); 20 | ``` 21 | 22 | ## Confirm Password 23 | 24 | Password fields can be used to update and confirm user passwords using the 25 | following `rules`. 26 | 27 | ```php 28 | $modal->password('password') 29 | ->title('New Password') 30 | ->rules('required', 'min:5') 31 | ->minScore(0); 32 | 33 | $modal->password('password_confirmation') 34 | ->rules('required', 'same:password') 35 | ->dontStore() 36 | ->title('New Password') 37 | ->noScore(); 38 | ``` 39 | 40 | ## Methods 41 | 42 | | Method | Description | 43 | | ------------------------------------ | ------------------------------------------------------------------------------ | 44 | | `$field->title('Password')` | The title description for this field. | 45 | | `$field->placeholder('Password')` | The placeholder for this field. | 46 | | `$field->hint('Choose a Password.')` | A short hint that should describe how to use the field.` | 47 | | `$field->info('...')` | Question mark with tooltip. (Can contain longer field descriptions) | 48 | | `$field->width(1/2)` | Width of the field. | 49 | | `$field->confirm()` | Requires the user to type in the current password to confirm update or create. | 50 | | `$field->rulesOnly()` | The password wont be stored, only validation rules are used. | 51 | | `$field->rules('min:5')` | Rules that should be applied when **updating** and **creating**. | 52 | | `$field->creationRules('min:5')` | Rules that should be applied when **creating**. | 53 | | `$field->updateRules('min:5')` | Rules that should be applied when **updating**. | 54 | -------------------------------------------------------------------------------- /fields/radio.md: -------------------------------------------------------------------------------- 1 | # Radio 2 | 3 | Radio inputs. 4 | 5 | ```php 6 | $form->radio('type') 7 | ->title('Type') 8 | ->options([ 9 | 'article' => 'Article', 10 | 'hint' => 'Hint', 11 | ]); 12 | ``` 13 | 14 | ## Methods 15 | 16 | | Method | Description | 17 | | ------------------------- | ------------------------------------------------------------------- | 18 | | `$field->title()` | The title description for this field. | 19 | | `$field->hint()` | A short hint that should describe how to use the field.` | 20 | | `$field->info()` | Question mark with tooltip. (Can contain longer field descriptions) | 21 | | `$field->width()` | Width of the field. | 22 | | `$field->options()` | An array with checkbox values and descriptions. | 23 | | `$field->stacked()` | Places each radio one over the other instead of next to each other. | 24 | | `$field->rules()` | Rules that should be applied when **updating** and **creating**. | 25 | | `$field->creationRules()` | Rules that should be applied when **creating**. | 26 | | `$field->updateRules()` | Rules that should be applied when **updating**. | 27 | -------------------------------------------------------------------------------- /fields/range.md: -------------------------------------------------------------------------------- 1 | # Range 2 | 3 | ## Introduction 4 | 5 | A range slider. 6 | 7 | ![Range slider](./screens/range/example.png 'Range slide') 8 | 9 | ## Example 10 | 11 | ```php 12 | $form->range('range') 13 | ->title('Range') 14 | ->min(1) 15 | ->max(4) 16 | ->step(1) 17 | ->hint('Range.') 18 | ->width(1/2); 19 | ``` 20 | 21 | ## Methods 22 | 23 | | Method | Description | 24 | | ------------------------- | ------------------------------------------------------------------ | 25 | | `$field->title()` | The title description for this field. | 26 | | `$field->hint()` | A short hint that should describe how to use the field.` | 27 | | `$field->info()` | Question mark with tooltip. (Can contain longer field descriptions) | 28 | | `$field->width()` | Width of the field. | 29 | | `$field->min()` | Minimum value. | 30 | | `$field->max()` | Maximum value. | 31 | | `$field->step()` | Steps. (default: 1) | 32 | | `$field->rules()` | Rules that should be applied when **updating** and **creating**. | 33 | | `$field->creationRules()` | Rules that should be applied when **creating**. | 34 | | `$field->updateRules()` | Rules that should be applied when **updating**. | 35 | -------------------------------------------------------------------------------- /fields/relation.md: -------------------------------------------------------------------------------- 1 | # Relation 2 | 3 | ## Introduction 4 | 5 | A relation picker. Relation pickers can be created for any relation of your 6 | model. 7 | 8 | ![relation picker](./screens/relation/picker.jpg 'relation picker') 9 | 10 | The relation field requires the name of the relation that should be edited. The 11 | type of the relation is automatically recognized and displayed accordingly. 12 | 13 | The relations Field can only be used for **Crud Models** and not in **Forms** or 14 | **Blocks**. For Forms or Blocks the [oneRelation](#onerelation-and-manyrelation) 15 | or [manyRelation](#onerelation-and-manyrelation) field can be used. 16 | 17 | ```php 18 | $form->relation('articles') 19 | ->title('Articles') 20 | ->preview(function ($table) { 21 | // Build the preview table in here. 22 | $table->col('title'); // In this case we are showing the article title. 23 | });; 24 | ``` 25 | 26 | In the Model: 27 | 28 | ```php 29 | public function articles() 30 | { 31 | return $this->hasMany('App/Models/Article'); 32 | } 33 | ``` 34 | 35 | ## Preview 36 | 37 | The table preview is configured in preview. 38 | 39 | ```php 40 | $form->relation('articles') 41 | ->title('Articles') 42 | ->preview(function ($table) { 43 | // Build the preview table in here. 44 | $table->col('title'); // In this case we are showing the article title. 45 | }); 46 | ``` 47 | 48 | However you don't need to define a new preview table every time you create a new 49 | relation field. You can simply display the index table of the related Model by 50 | setting settings its Crud config class in the `use` method list this: 51 | 52 | ```php 53 | use Lit\Config\Crud\ArticleConfig; 54 | 55 | $form->relation('articles') 56 | ->title('Articles') 57 | ->use(ArticleConfig::class); 58 | ``` 59 | 60 | ### Display Pivot Data 61 | 62 | You may load and display data from the pivot table of a many to many relation. 63 | 64 | In the following example we want to display when a subscription of a user 65 | expires: 66 | 67 | First load the pivot data by specifying the desired columns in the `withPivot` 68 | method: 69 | 70 | ```php 71 | $index->query(function($query) { 72 | $query->withPivot('expires_at'); 73 | }); 74 | ``` 75 | 76 | Now we can display the `expires_at` attribute like this: 77 | 78 | ```php 79 | $field->preview(function ($table) { 80 | $table->col('subscriptions.pivot.expires_at'); 81 | }); 82 | ``` 83 | 84 | ## Sortable 85 | 86 | If the relation should be sortable, the related query in your Model must be 87 | sorted by an `orderColumn`. 88 | 89 | ```php 90 | public function articles() 91 | { 92 | return $this->hasMany('App/Models/Article')->orderBy('order_column'); 93 | } 94 | ``` 95 | 96 | Now the sortable attribute can be added: 97 | 98 | ```php 99 | $form->relation('articles') 100 | ->title('Articles') 101 | ->sortable() 102 | ->preview(function ($table) { 103 | $table->col('Title')->value('{title}'); 104 | }); 105 | ``` 106 | 107 | ## Filter 108 | 109 | With a **filter** you can specify which models can be selected for a relation. 110 | 111 | ```php 112 | $form->relation('articles') 113 | ->title('Articles') 114 | ->filter(function($query) { 115 | $query->where('created_by', lit_user()->id); 116 | }); 117 | ``` 118 | 119 | ## Forms 120 | 121 | You can edit the **related attributes** in a modal by configuring fields in the 122 | form method: 123 | 124 | ```php 125 | $form->relation('articles') 126 | ->form(function($form) { 127 | $form->wysiwyg('text')->title('text'); 128 | }); 129 | ``` 130 | 131 | ### Create A New Relationship Model 132 | 133 | You may also add a create form so the user can create new relationship models 134 | directly: 135 | 136 | ```php 137 | $form->relation('articles') 138 | ->create(function($form) { 139 | $form->wysiwyg('text')->title('text'); 140 | }); 141 | ``` 142 | 143 | ::: tip 144 | 145 | Set a create and edit form using the `createAndUpdateForm`. 146 | 147 | ::: 148 | 149 | ### Pivot Fields 150 | 151 | Sometimes you may want to edit pivot data such as the `expired_at` date of a 152 | **subscription**. Therefore the `pivot` method must be prepended to the field. 153 | 154 | ```php 155 | $field->form(function($form) { 156 | $form->pivot()->datetime('expires_at')->title('Expires At'); 157 | }); 158 | ``` 159 | 160 | ## Inline Fields 161 | 162 | You may even add inline fields to your relationship table. The following example 163 | show's how to add an relationship to opening hours that can be created and 164 | edited directly: 165 | 166 | ![Relation Inline Fields](./screens/relation/inline.png 'Relation Inline Fields') 167 | 168 | ```php 169 | $form->relation('openingHours') 170 | ->title('Opening Hours') 171 | ->showTableHead() 172 | ->deleteUnlinked() 173 | ->hideRelationLink() 174 | ->names([ 175 | 'singular' => 'Opening Hour', 176 | 'plural' => 'Opening Hours', 177 | ]) 178 | ->preview(function ($preview) { 179 | $preview->col('Week Day')->value('{week_day}'); 180 | 181 | $preview->field('Opening Time') 182 | ->datetime('opening_time') 183 | ->onlyTime() 184 | ->minuteInterval(15); 185 | 186 | $preview->field('Closing Time') 187 | ->datetime('closing_time') 188 | ->onlyTime() 189 | ->minuteInterval(15); 190 | }) 191 | ->create(function ($form) { 192 | $form->select('week_day') 193 | ->title('Wochentag') 194 | ->options([ 195 | 'monday' => 'Monday', 196 | 'tuesday' => 'Tuesday', 197 | 'wednesday' => 'Wednesday', 198 | 'thursday' => 'Thursday', 199 | 'friday' => 'Friday', 200 | 'saturday' => 'Saturday', 201 | 'sunday' => 'Sunday', 202 | ]); 203 | $form->datetime('opening_time') 204 | ->onlyTime() 205 | ->minuteInterval(15) 206 | ->width(1 / 2); 207 | 208 | $form->datetime('closing_time') 209 | ->onlyTime() 210 | ->minuteInterval(15) 211 | ->width(1 / 2); 212 | }); 213 | ``` 214 | 215 | ## Eager Loading & Appending Accessors 216 | 217 | With query, **relationships** & **accessors** that should be displayed can be 218 | **eager loaded** or **appended**. 219 | 220 | ```php 221 | $form->relation('articles') 222 | ->title('Articles') 223 | ->query(function($query) { 224 | $query->with('author')->append('comments_count'); 225 | }) 226 | ->preview(function ($table) { 227 | $table->col('Author')->value('{author.first_name} {author.last_name}'); 228 | $table->col('Comments')->value('{comments_count} comments'); 229 | }); 230 | ``` 231 | 232 | ## Allow Direct Unlink 233 | 234 | To switch off the modal in which unlinking a relation is confirmed, `confirm` 235 | must be set to false. 236 | 237 | ```php 238 | $form->relation('articles') 239 | ->confirm(false); 240 | ``` 241 | 242 | ## Delete Unlinked Model 243 | 244 | You may wish to delete a relation when it has been unlinked: 245 | 246 | ```php 247 | $form->relation('articles') 248 | ->deleteUnlinked(); 249 | ``` 250 | 251 | ## Tags 252 | 253 | For **many relations** a `tag` preview can be generated by passing `tags` to the 254 | `type` method. Therefore the **attribute** that should be displayed in the tag 255 | must be specified using `tagValue`. Furthermore the variant can be specified 256 | with `tagVariant`. 257 | 258 | ```php 259 | $form->relation('tags') 260 | ->title('Tags') 261 | ->type('tags') 262 | ->tagValue('{value}'); 263 | ``` 264 | 265 | ![Relation Tags](./screens/relation/tags.png 'Relation Tags') 266 | 267 | ## oneRelation And manyRelation 268 | 269 | Every Laravel relation needs its corresponding database setup. For example the 270 | belongsTo relation needs an extra column that stores the id of the related 271 | Model. However you migth want to create relations without going through the 272 | process of creating a new migration to add the required columns/tables. For this 273 | there is the `oneRelation` and `manyRelation`. They can simply be added to your 274 | Models or Forms. 275 | 276 | The following example shows the simple setup of a the relation field that works 277 | for both: 278 | 279 | ```php 280 | use App\Models\Article; 281 | 282 | $form->manyRelation('articles') 283 | ->title('Articles') 284 | ->model(Article::class) 285 | ->preview(function($preview) { 286 | //... 287 | }); 288 | ``` 289 | 290 | In the Model: 291 | 292 | ```php 293 | public function articles() 294 | { 295 | return $this->manyRelation('App/Models/Article', 'articles'); 296 | } 297 | ``` 298 | 299 | :::tip 300 | 301 | `oneRelation` and `manyRelation` can be used in Forms. 302 | 303 | ::: 304 | 305 | ## Methods 306 | 307 | | Method | Description | 308 | | ------------------------------- | --------------------------------------------------------------------------------------------------------- | 309 | | `$field->title(')` | The title description for this field. | 310 | | `$field->hint(')` | A short hint that should describe how to use the field.` | 311 | | `$field->width()` | Width of the field. | 312 | | `$field->filter()` | Initial query builder for the selectable relations. | 313 | | `$field->query()` | Modify preview query with eager loads and accessors that should be displayed. | 314 | | `$field->preview()` | A **closure** to define the table preview of the corresponding relation. | 315 | | `$field->confirm()` | Modal pops when unlinking the relation and asks to confirm. (default: `true`) | 316 | | `$field->deleteUnlinked()` | Deletes the relation Model after unlinking the relation. (default: `false`) | 317 | | `$field->sortable()` | Sortable relation (only works for `many` relations). | 318 | | `$field->small()` | Small table column height. | 319 | | `$field->maxItems()` | Set a maximum number of selectable items (only works for `many` relations). | 320 | | `$field->create()` | Define form fields for a create form so users can crete new relationship models directly. | 321 | | `$field->form()` | Define form fields so the user can update relation ship attributes. | 322 | | `$field->createAndUpdateForm()` | Define the same form fields for `create` and `form`. | 323 | | `$field->showTableHead()` | Whether the table head should be shown. (default: `false`) | 324 | | `$field->type()` | The preview type (default: `table`) can be `tags` for **many relations** and `link` for **one relations** | 325 | | `$field->tagValue()` | The attribute that should be displayed in the tag. | 326 | | `$field->tagVariant()` | The bootstrap variant of the tag. (default: `info`) | 327 | | `$field->linkValue()` | The attributes that should be displayed as the link. | 328 | -------------------------------------------------------------------------------- /fields/route.md: -------------------------------------------------------------------------------- 1 | # Route Field 2 | 3 | ## Introduction 4 | 5 | A route picker field that lets you select routes from a predefined collection. 6 | 7 | ## Usage 8 | 9 | The route field requires the **name** of the [collection](#route-collection) 10 | that should be used for this field. Additionally a **title** is required. 11 | 12 | ```php 13 | $form->route('route') 14 | ->collection('app') 15 | ->title('Pick an Url'); 16 | ``` 17 | 18 | ## Route Collection 19 | 20 | To be able to select routes in your route field you must first register a route 21 | collection in a [service provider](https://laravel.com/docs/7.x/providers). The 22 | registered collection can then be used again and again in different places. The 23 | following example registers a collection with the name **app**. 24 | 25 | ```php 26 | use Ignite\Crud\Fields\Route; 27 | 28 | Route::register('app', function($collection) { 29 | // Define your route collection in here. 30 | }); 31 | ``` 32 | 33 | ### Add Route 34 | 35 | The selectable routes are configured in the closure using the `route` method. 36 | The first parameter is the **title** that represents the route followed by an 37 | identifier and a function that returns the actual route. 38 | 39 | ```php 40 | $collection->route('Home', 'home', function() { 41 | return route('home'); 42 | }); 43 | ``` 44 | 45 | :::tip 46 | 47 | Use the [arrow function](https://www.php.net/manual/en/functions.arrow.php) 48 | short cut: 49 | 50 | ```php 51 | $collection->route('Home', 'home', fn($locale) => route('home')); 52 | ``` 53 | 54 | ::: 55 | 56 | ### Add Group 57 | 58 | You can group routes for example into model show routes. 59 | 60 | ```php 61 | $collection->group('Articles', function($group) { 62 | $articles = Article::all(); 63 | 64 | foreach($articles as $article) { 65 | $group->route($article->title, $article->id, function() use ($article) { 66 | return route('articles.show', $article->id)); 67 | }); 68 | } 69 | }); 70 | ``` 71 | 72 | ### Localization 73 | 74 | The closure in which the route is returned is given the current **locale** as 75 | parameter. 76 | 77 | ```php 78 | $collection->route('Home', 'home' function($locale) { 79 | return route("{$locale}.home"); 80 | }); 81 | ``` 82 | 83 | ## Prepare Model 84 | 85 | If the route field is used in Models the route cast must be specified: 86 | 87 | ```php 88 | use Ignite\Crud\Casts\Route; 89 | 90 | $casts = [ 91 | 'route' => Route::class 92 | ]; 93 | ``` 94 | 95 | ## Frontend 96 | 97 | You can output the value of your route directly in Blade, for example in the 98 | **href** attribute like this: 99 | 100 | ```php 101 | My Link 102 | ``` 103 | 104 | You can check if the route is active: 105 | 106 | ```php 107 | @if($model->route->isActive()) 108 | Hello World! 109 | @endif 110 | ``` 111 | 112 | You may use the `isActive` method to add optional classes to your link: 113 | 114 | ```php 115 | 119 | My Link 120 | 121 | ``` 122 | -------------------------------------------------------------------------------- /fields/screens/conditions/conditions_radio.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/conditions/conditions_radio.gif -------------------------------------------------------------------------------- /fields/screens/datetime/date_and_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/datetime/date_and_time.png -------------------------------------------------------------------------------- /fields/screens/datetime/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/datetime/example.png -------------------------------------------------------------------------------- /fields/screens/image/expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/image/expand.png -------------------------------------------------------------------------------- /fields/screens/image/first_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/image/first_big.png -------------------------------------------------------------------------------- /fields/screens/range/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/range/example.png -------------------------------------------------------------------------------- /fields/screens/relation/inline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/relation/inline.png -------------------------------------------------------------------------------- /fields/screens/relation/picker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/relation/picker.jpg -------------------------------------------------------------------------------- /fields/screens/relation/tags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/relation/tags.png -------------------------------------------------------------------------------- /fields/screens/validation/validation_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/fields/screens/validation/validation_1.png -------------------------------------------------------------------------------- /fields/select.md: -------------------------------------------------------------------------------- 1 | # Select 2 | 3 | A select field. 4 | 5 | ```php 6 | $form->select('article_type') 7 | ->title('Type') 8 | ->options([ 9 | 1 => 'News', 10 | 2 => 'Info', 11 | ]) 12 | ->hint('Select the article type.'); 13 | ``` 14 | 15 | ## BelongsTo 16 | 17 | A select can be used for `belongsTo` relations. 18 | 19 | ```php 20 | $form->select('article_id') 21 | ->title('Article') 22 | ->options( 23 | Article::all()->mapWithKeys(function($item, $key){ 24 | return [$item->id => $item->title]; 25 | })->toArray() 26 | ) 27 | ->hint('Select Article.'); 28 | ``` 29 | 30 | ## Methods 31 | 32 | | Methods | Description | 33 | | ------------------------- | ---------------------------------------------------------------------- | 34 | | `$field->title()` | The title description for this field. | 35 | | `$field->options()` | An array with the options, can be a simple array or key => value pairs | 36 | | `$field->hint()` | A short hint that should describe how to use the field.` | 37 | | `$field->info()` | Question mark with tooltip. (Can contain longer field descriptions) | 38 | | `$field->width()` | Width of the field. | 39 | | `$field->rules()` | Rules that should be applied when **updating** and **creating**. | 40 | | `$field->creationRules()` | Rules that should be applied when **creating**. | 41 | | `$field->updateRules()` | Rules that should be applied when **updating**. | 42 | -------------------------------------------------------------------------------- /fields/textarea.md: -------------------------------------------------------------------------------- 1 | # Textarea 2 | 3 | Basic textarea field. 4 | 5 | ```php 6 | $form->textarea('text') 7 | ->translatable() 8 | ->title('Description') 9 | ->placeholder('Type something...') 10 | ->hint('The Description for some Object.') 11 | ->width(1/2); 12 | ``` 13 | 14 | ## Methods 15 | 16 | | Method | Description | 17 | | ------------------------- | --------------------------------------------------------------------------------------------------------------------- | 18 | | `$field->title()` | The title description for this field. | 19 | | `$field->placeholder()` | The placeholder for this field. | 20 | | `$field->hint()` | A short hint that should describe how to use the field.` | 21 | | `$field->info()` | Question mark with tooltip. (Can contain longer field descriptions) | 22 | | `$field->width()` | Width of the field. | 23 | | `$field->translatable()` | Should the field be translatable? For translatable crud models, the translatable fields are automatically recognized. | 24 | | `$field->max()` | Max characters. | 25 | | `$field->rows()` | Number of rows. | 26 | | `$field->maxRows()` | Maximum number of rows. | 27 | | `$field->rules()` | Rules that should be applied when **updating** and **creating**. | 28 | | `$field->creationRules()` | Rules that should be applied when **creating**. | 29 | | `$field->updateRules()` | Rules that should be applied when **updating**. | 30 | -------------------------------------------------------------------------------- /fields/validation.md: -------------------------------------------------------------------------------- 1 | # Field Validation 2 | 3 | Fields that are not **validated** entail security risks, any values can be 4 | stored for all fillable attributes without validation. It is therefore highly 5 | recommended to append validation rules to any field that handles a fillable 6 | attribute. The 7 | [Laravel documentation](https://laravel.com/docs/7.x/validation#available-validation-rules) 8 | describes all existing rules that can be used for request validation. 9 | 10 | ## Attach Rules 11 | 12 | The following example shows how the rules are attached to a field: 13 | 14 | ```php 15 | $form->input('text') 16 | ->title('Text') 17 | ->rules('required', 'min:10', 'max:50'); 18 | ``` 19 | 20 | The **error messages** are displayed directly below the field. The **title** is 21 | displayed as attribute. 22 | 23 | ![Field Validation](./screens/validation/validation_1.png 'Lit field validation') 24 | 25 | ::: tip 26 | 27 | litstack only sends fields that have changed when saving. So keep in mind that 28 | you probably want add the `required` rule to `creationRules`. 29 | 30 | ::: 31 | 32 | ## Update Rules 33 | 34 | All rules specified via the method `rules` apply to the creation and updating of 35 | a model. Rules that should only apply for updating a model are defined in 36 | `updateRules` like this: 37 | 38 | ```php 39 | $form->input('text') 40 | ->title('Text') 41 | ->rules('min:10') 42 | ->updateRules('max:50'); 43 | ``` 44 | 45 | ## Creation Rules 46 | 47 | Similarly, rules can be specified only for creating a model. 48 | 49 | ```php 50 | $form->input('text') 51 | ->title('Text') 52 | ->rules('min:10', 'max:50') 53 | ->creationRules('required'); 54 | ``` 55 | -------------------------------------------------------------------------------- /fields/wysiwyg.md: -------------------------------------------------------------------------------- 1 | # WYSIWYG 2 | 3 | A **W**hat-**Y**ou-**S**ee-**I**s-**W**hat-You-**G**et editor using 4 | [tiptap](https://github.com/scrumpy/tiptap). 5 | 6 | ```php 7 | $form->wysiwyg('text') 8 | ->translatable() 9 | ->colors([ 10 | '#4951f2', '#f67693', '#f6ed76', '#9ff2ae', '#83c2ff' 11 | ]) 12 | ->title('Description') 13 | ->hint('What you see is what you get field.'); 14 | ``` 15 | 16 | ## Methods 17 | 18 | | Method | Description | 19 | | -------------------------- | --------------------------------------------------------------------------------------------------------------------- | 20 | | `$field->title()` | The title description for this field. | 21 | | `$field->hint()` | A short hint that should describe how to use the field.` | 22 | | `$field->info()` | Question mark with tooltip. (Can contain longer field descriptions) | 23 | | `$field->width()` | Width of the field. | 24 | | `$field->translatable()` | Should the field be translatable? For translatable crud models, the translatable fields are automatically recognized. | 25 | | `$field->max()` | Max characters. | 26 | | `$field->colors()` | Array of colors the the text can be painted in. | 27 | | `$field->tableHasHeader()` | Determines if wysiwyg tables should have an header. | 28 | | `$field->rules()` | Rules that should be applied when **updating** and **creating**. | 29 | | `$field->creationRules()` | Rules that should be applied when **creating**. | 30 | | `$field->updateRules()` | Rules that should be applied when **updating**. | 31 | -------------------------------------------------------------------------------- /frontend/components.md: -------------------------------------------------------------------------------- 1 | # Vue Components 2 | 3 | ## Introduction 4 | 5 | The package comes along with **bootstrap-vue** and a few components that can be 6 | used to build pages that fit the package's style. To ensure that users of the 7 | admin interface can find their way around quickly and easily on all sites, it is 8 | recommended to follow the following guidelines. 9 | 10 | The package's components have the prefix `lit-`. 11 | 12 | ## Custom Pages 13 | 14 | Custom pages for the admin panel consist of a `container`, the topbar 15 | `navigation` and a `header`. The following content can be created as you like. 16 | 17 | The following example shows how the root template of a page looks like. 18 | 19 | ```javascript 20 | 28 | 29 | 34 | ``` 35 | 36 | It is recommended to wrap your page content with a b-row and lit-col components. 37 | 38 | ```javascript 39 | 48 | ``` 49 | 50 | ## Navigation 51 | 52 | The topbar navigation is designed to make it easier for the user to navigate 53 | through the interface and display important controls while scrolling. 54 | 55 | ```javascript 56 | 57 | ``` 58 | 59 | ### Go Back 60 | 61 | In the topbar navigation a **back** button can be displayed. All pages in admin 62 | application should be reached via at most one more link from the main 63 | navigation, i.e. an **overview** page and the **detail** page. 64 | 65 | To display the back link a text for the button and a link must be passed as prop 66 | to the navigation. 67 | 68 | ```php 69 | 70 | ``` 71 | 72 | ### Controls 73 | 74 | To display controls in the tooltip, simply specify an array with component 75 | names. 76 | 77 | ```javascript 78 | 79 | ``` 80 | 81 | The components for the controls must use the bootstrap `b-dropdown-item` as a 82 | root component like so: 83 | 84 | ```javascript 85 | 90 | 91 | 101 | ``` 102 | 103 | Furthermore, the `left` and `right` slot can be used to display buttons 104 | directly. 105 | 106 | ```php 107 | 108 | 109 | Left Action 110 | 111 | 112 | Right Action 113 | 114 | 115 | ``` 116 | 117 | ## Header 118 | 119 | The page header consists of an `h3` header. The title can either be specified 120 | via the prop `title` or designed in the main slot. 121 | 122 | As well the header can contain controls that should be displayed under the 123 | header. The controls are displayed with the slots `actions` and `actions-right`. 124 | 125 | ```javascript 126 | 127 | 128 | Left Action 129 | 130 | 131 | Right Action 132 | 133 | 134 | ``` 135 | 136 | ## Spinner 137 | 138 | The spinner can be displayed with the component `lit-spinner`. 139 | 140 | ```javascript 141 | 144 | ``` 145 | -------------------------------------------------------------------------------- /frontend/javascript.md: -------------------------------------------------------------------------------- 1 | # Javascript 2 | 3 | ## Introduction 4 | 5 | If you build your own Vue components it makes sense to know about the helpers 6 | available in Javascript. 7 | 8 | ## Axios 9 | 10 | The javascript global `axios` is configured with the route prefix specified in 11 | the config **lit.php**. It is recommended to set a try around the function when 12 | executing an axios request. 13 | 14 | ```javascript 15 | async func() { 16 | let response; 17 | try { 18 | response = await axios.get('my-route') 19 | } catch(e) { 20 | return 21 | } 22 | 23 | ... 24 | } 25 | ``` 26 | 27 | ::: tip 28 | 29 | For requests that shouldn't use the admin `route_prefix` the global `_axios` can 30 | be used. 31 | 32 | ::: 33 | 34 | ## Helpers 35 | 36 | In javascript and all Vue components the global variable `Lit` is available. 37 | This includes the following helpers: 38 | 39 | - `baseURL` 40 | - `config` 41 | 42 | ### `Lit.baseURL` 43 | 44 | The `route_prefix` set in config **lit.php**, with a front slash before and 45 | after the prefix. 46 | 47 | ```php 48 | // config/lit.php 49 | 'route_prefix' => 'admin' // Lit.baseURL would be /admin/ 50 | ``` 51 | 52 | ```javascript 53 | 54 | Link 55 | 56 | ``` 57 | 58 | ### `Lit.config` 59 | 60 | All attributes from the config **lit.php**. 61 | 62 | ## Event Bus 63 | 64 | The event bus can be called via the global Lit like this: 65 | 66 | ```javascript 67 | Lit.bus.$on(event, callback); 68 | Lit.bus.$once(event, callback); 69 | Lit.bus.$off(event, callback); 70 | Lit.bus.$emit(event, callback); 71 | ``` 72 | 73 | ## Events 74 | 75 | Some useful events: 76 | 77 | - `saved` - Executed when saved. 78 | - `saveCanceled` - When save has been canceled. 79 | -------------------------------------------------------------------------------- /frontend/vue.md: -------------------------------------------------------------------------------- 1 | # Vue 2 | 3 | ## Introduction 4 | 5 | The admin interface can be extended with custom Vue components for numerous 6 | purposes. This documents describes how custom Vue components can be added to the 7 | application. 8 | 9 | ## Extend Vue 10 | 11 | To include your own `Vue` components in the admin application, the local npm 12 | package `vendor/litstack/litstack` has to be installed. This can be done using 13 | the following artisan command: 14 | 15 | ```shell 16 | php artisan lit:extend 17 | ``` 18 | 19 | At the beginning of your `webpack.mix.js` the import of the Litstack mix config 20 | will be added automatically. Two files are compiled: 21 | 22 | - `lit/resources/js/app.js` => `public/lit/js/app.js` 23 | - `lit/resources/sass/app.scss` => `public/lit/css/app.css` 24 | 25 | Add them to **assets** in the config. 26 | 27 | ```php{config/lit.php} 28 | 'assets' => [ 29 | 'app_js' => '/lit/js/app.js', 30 | 'scripts' => [ 31 | // Add more js files here ... 32 | ], 33 | 'styles' => [ 34 | // Add more css files here ... 35 | ], 36 | ], 37 | ``` 38 | 39 | All javascript files can be found in `lit/resources/js`. 40 | 41 | ::: tip 42 | 43 | Components that are created in the `components` folder are automatically 44 | registered. 45 | 46 | ::: 47 | 48 | Run `npm run watch` and you are good to go. 49 | 50 | ::: warning 51 | 52 | Don't forget to compile your assets every time you **update** the package. 53 | 54 | ::: 55 | 56 | ## Register Vue Components 57 | 58 | Vue Components that are located in the `./lit/resources/js/components` folder 59 | are automatically globally registered. They can be used for example in Pages, 60 | Tables or anywhere where you want to include Vue components. 61 | 62 | ## Bootstrap Vue 63 | 64 | To make it easy to build uniform Litstack pages, the package uses 65 | [Bootstrap Vue](https://bootstrap-vue.org/docs/components) for all frontend 66 | components. Bootstrap Vue comes with a large number of components to cover all 67 | the necessary areas needed to build an application. 68 | 69 | ## Mixins 70 | 71 | - [can](#mixin-can) 72 | - [user](#mixin-user) 73 | 74 | 75 | 76 | ### `can({permission})` 77 | 78 | The `can` mixin checks if the authenticated user has a permission. 79 | 80 | ```js 81 | 82 | ``` 83 | 84 | 85 | 86 | ### `user()` 87 | 88 | The `user` mixin returns the authenticated User Model. 89 | 90 | ```js 91 | {{ user().name }} 92 | ``` 93 | 94 | ## Localization 95 | 96 | [i18n-vue](https://kazupon.github.io/vue-i18n/docs/formatting.html) is used for 97 | the translation in Vue. All translations that are available in **php** are 98 | available in **i18n-vue** as well like shown in the example: 99 | 100 | ```php{lit/resources/lang/en/message.php} 101 | return [ 102 | "welcome": "Welcome to Litstack" 103 | ]; 104 | ``` 105 | 106 | ```javascript 107 |
108 | {{ $t('message.welcome') }} 109 |
110 | ``` 111 | -------------------------------------------------------------------------------- /installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## Requirements 4 | 5 | An existing Laravel project is required to install the package as well as a 6 | database connection. The package requires **PHP 7.4+** and **Laravel 7+**. As 7 | well as all 8 | [requirements](https://docs.spatie.be/laravel-medialibrary/v8/requirements) of 9 | **spatie/laravel-medialibrary 8.2+**. 10 | 11 | ## Setup 12 | 13 | Installing the package into an existing Laravel application via Composer: 14 | 15 | ```shell 16 | composer require litstack/litstack 17 | ``` 18 | 19 | The application will automatically register the needed service providers. The 20 | next step is to process all publishes and migrations by typing the following 21 | artisan command: 22 | 23 | ```shell 24 | php artisan lit:install 25 | ``` 26 | 27 | Now all models have been moved to the `app/models` folder, all required files 28 | have been published and all migrations have been executed. 29 | 30 | The admin interface can be reached via the standard route `/admin`. The route 31 | may be changed in the config file `lit.php` by changing the `route_prefix` key. 32 | 33 | The final step is to create an admin user so you can log in to the backend: 34 | 35 | ```shell 36 | php artisan lit:admin 37 | ``` 38 | 39 | The wizard will guide you through the process of entering the required user 40 | data. 41 | -------------------------------------------------------------------------------- /packages/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/packages/.DS_Store -------------------------------------------------------------------------------- /packages/2fa.md: -------------------------------------------------------------------------------- 1 | # 2 Factor Authentication 2 | 3 | 6 | 7 | ## Introduction 8 | 9 | A package to add 2 Factor Authentication to your litstack application. Secure 10 | the login or the submitting of forms. 11 | 12 | ## The verify Field 13 | 14 | With the verify field a form can be confirmed with a one time password become. 15 | 16 | ```php 17 | $form->input('header'); 18 | 19 | $form->needsVerification(); 20 | ``` 21 | 22 | ![verify field](./screens/verify.gif) 23 | 24 | ::: tip 25 | 26 | If the authenticated user hasn't activated 2 factor authentication for his 27 | account. He is asked to verify the form using his password. 28 | 29 | ::: 30 | 31 | 38 | 39 | ## Setup 40 | 41 | 53 | 54 | Install the package via composer: 55 | 56 | ```shell 57 | composer require litstack/2fa 58 | ``` 59 | 60 | ## User Model 61 | 62 | Too enable 2 factor authentication on the model used for the litstack 63 | authentication it must add the 2 columns to the corresponding table: 64 | 65 | ```shell 66 | pa make:migration add_two_fa_columns_to_lit_users_table 67 | ``` 68 | 69 | ```php 70 | class AddTwoFaColumnsToLitUsersTable extends Migration 71 | { 72 | public function up() 73 | { 74 | Schema::table('lit_users', function (Blueprint $table) { 75 | $table->boolean('two_fa_enabled'); 76 | $table->text('two_fa_secret'); 77 | }); 78 | } 79 | 80 | public function down() 81 | { 82 | Schema::table('lit_users', function (Blueprint $table) { 83 | $table->dropColumn('two_fa_enabled'); 84 | $table->dropColumn('two_fa_secret'); 85 | }); 86 | } 87 | } 88 | ``` 89 | 90 | Execute the migration: 91 | 92 | ```shell 93 | php artisan migrate 94 | ``` 95 | 96 | Now your Model needs to implement the `Litstack\TwoFA\Authenticatable` contract 97 | and use the `Litstack\TwoFA\HasTwoFactorAuthentication` trait: 98 | 99 | ```php{lit/app/Models/User.php} 100 | // ... 101 | 102 | use Litstack\TwoFA\Authenticatable as TwoFA; 103 | use Litstack\TwoFA\HasTwoFactorAuthentication; 104 | 105 | class User extends Authenticatable implements CanResetPasswordContract, TwoFA 106 | { 107 | use HasTwoFactorAuthentication; 108 | 109 | // ... 110 | } 111 | ``` 112 | 113 | The final thing you need to do, is adding the `two_fa_secret` to the `hidden` 114 | attributes of your model and the `two_fa_enabled` as a **boolean** `cast` like 115 | this: 116 | 117 | ```php{lit/app/Models/User.php} 118 | /** 119 | * Hidden attributes. 120 | * 121 | * @var array 122 | */ 123 | protected $hidden = ['password', 'two_fa_secret']; 124 | 125 | /** 126 | * The attributes that should be cast to native types. 127 | * 128 | * @var array 129 | */ 130 | protected $casts = [ 131 | 'email_verified_at' => 'datetime', 132 | 'two_fa_enabled' => 'boolean', 133 | ]; 134 | ``` 135 | -------------------------------------------------------------------------------- /packages/bladesmith.md: -------------------------------------------------------------------------------- 1 | # Bladesmith 2 | 3 | 4 | 5 | ## Introduction 6 | 7 | A package with helper functions and Blade components for your 8 | [Litstack](https://github.com/litstack/litstack) project. 9 | 10 | ## Sponsorware 11 | 12 | Bladesmith was created by 13 | **[Lennart Carstens-Behrens](https://twitter.com/lennartcb)** under the 14 | **[Sponsorware license](https://github.com/sponsorware/docs)**. 15 | 16 | ::: tip 17 | 18 | [Sponsor litstack](https://github.com/sponsors/litstack) to get access to this 19 | package. 20 | 21 | ::: 22 | 23 | ## Setup 24 | 25 | Add the Litstack repository to your application's composer.json file: 26 | 27 | ```json 28 | "repositories": [ 29 | { 30 | "type": "composer", 31 | "url": "https://store.litstack.io" 32 | } 33 | ], 34 | ``` 35 | 36 | ```shell 37 | composer require litstack/bladesmith 38 | ``` 39 | 40 | To include all styles and scripts the `x-styles` tag must be placed in the head 41 | and the `x-scripts` tag at the end of the body. 42 | 43 | ```html 44 | 45 | 46 | 47 | ... 48 | 49 | 50 | 51 | 52 | ... 53 | 54 | 55 | 56 | 57 | ``` 58 | 59 | ## Image 60 | 61 | The image component uses lazy loading to preview a base64 string of the image 62 | before loading it. The image will be loaded when it gets scrolled into the 63 | screen. The component also outputs the appropriate media conversion for the 64 | corresponding screen sizes. 65 | 66 | The component requires an image parameter with a media model: 67 | 68 | ```php 69 | 70 | ``` 71 | 72 | ![litstack lazy loading](./screens/lazy.png) 73 | 74 | Lazy loading may disabled by setting the `lazy` attribute to false: 75 | 76 | ```php 77 | 78 | ``` 79 | 80 | ## Building Navigations in Litstack 81 | 82 | Every page needs a navigation. Building it often takes time, especially if the 83 | design has to be adapted exactly to your needs. The Ui kit comes with a simple 84 | extensive solution to include all possible navigations types that are built with 85 | a `list` field in a short time. 86 | 87 | ### Create the Form 88 | 89 | We start by creating a form in that we can build our navigation: 90 | 91 | ```shell 92 | php artisan lit:form navigations main_navigation 93 | ``` 94 | 95 | The next step is to add a `nav` field to the newly created config file: 96 | 97 | ```php 98 | namespace Lit\Config\Form\Navigations; 99 | 100 | class MainNavigationConfig extends FormConfig 101 | { 102 | public function show(CrudShow $page) 103 | { 104 | $page->card(function ($form) { 105 | $form->nav('main')->title('Main Navigation')->maxDepth(3); 106 | }); 107 | } 108 | } 109 | ``` 110 | 111 |

112 | 113 |

114 | 115 | Now we can simply pass the list field to the `x-lit-nav-list` component and a 116 | navigation is created that can be build in the litstack backend: 117 | 118 | ### Display the Navigation 119 | 120 | ```php 121 | use Ignite\Support\Facades\Form; 122 | 123 | $nav = Form::load('navigations', 'main_navigation'); 124 | 125 | 126 | ``` 127 | 128 | This will result in the following simple horizontal navigation: 129 | 130 |

131 | 132 |

133 | 134 | Customize the navigation using the following options 135 | 136 | | Method | Description | 137 | | ------------- | ---------------------------------------------------------------------- | 138 | | `layout` | Can be `horizontal` or `vertical`. (default is `vertical`) | 139 | | `dropdown` | Wether the navigation should be a dropdown menue on `mouseover`. | 140 | | `depth` | Max depth. | 141 | | `subLevel` | Start depth. | 142 | | `expandable` | Only display's level one, all child levels can be expanded on `click`. | 143 | | `class` | Navigation class. | 144 | | `activeClass` | Class of active items. (default is: `lit--active`) | 145 | 146 | ## Translatable Routes 147 | 148 | Build translated routes in the form of `/en/home`, `/de/startseite` made easy. 149 | 150 | Make sure to translate your routes within your translation-files in the 151 | `resources` directory, for example: 152 | 153 | ```php 154 | // lang/de/routes.php 155 | 156 | return [ 157 | 'home' => 'startseite' 158 | ]; 159 | ``` 160 | 161 | You can now simply add translated Routes to your preferred routes file using the 162 | `__()` helper in the uri string like this: 163 | 164 | ```php 165 | Route::trans('/__(routes.home)', 'HomeController@show')->name('home'); 166 | ``` 167 | 168 | A translated route will be created for all locales defined in your 169 | `translatable` config. The locale will be prepended to the given **uri** and 170 | **name**. So the routes for the previous example would be: 171 | 172 | - `en.home` => `/en/home` 173 | - `de.home` => `/de/startseite` 174 | 175 | The `__route` helper prepends the current locale to the given name and returns 176 | the corresponding route: 177 | 178 | ```php 179 | 180 | ... 181 | 182 | ``` 183 | 184 | ### Switching Languages 185 | 186 | You may want to place a link to the different language route on your website. To 187 | do this, the `translate` method can be applied to the current route with the 188 | desired locale. 189 | 190 | ```php 191 | Deutsch 192 | ``` 193 | 194 | #### With Parameters 195 | 196 | For routes with parameters a translator must be specified. A translator is a 197 | controller method that returns the route parameters for the desired locale. The 198 | translator method receives the desired locale and the parameters for the current 199 | locale. 200 | 201 | ```php 202 | // ./routes/web.php 203 | Route::trans('/{slug}', 'MyController@show')->translator('getSlug')->name('home'); 204 | 205 | // ./app/Http/Controllers/MyController.php 206 | 207 | ... 208 | 209 | class MyController extends Controller 210 | { 211 | ... 212 | 213 | public function getSlug($locale, $slug) 214 | { 215 | $slug = Post::whereTranslation('slug', $slug) 216 | ->first() 217 | ->translate($locale) 218 | ->slug; 219 | 220 | return ['slug' => $slug]; 221 | } 222 | } 223 | ``` 224 | 225 | ### Language Switch 226 | 227 | The Blade component `x-lit-localize` creates a link to the translated routes of 228 | all locales. 229 | 230 | ```html 231 | 232 | ``` 233 | 234 | Result: 235 | 236 | ```html 237 | EN 238 | DE 239 | ``` 240 | 241 | You may change the content of the link By passing a slot with the name of the 242 | locale: 243 | 244 | ```html 245 | 246 | 247 | English 248 | 249 | 250 | Deutsch 251 | 252 | 253 | ``` 254 | 255 | Result: 256 | 257 | ```html 258 | English 259 | Deutsch 260 | ``` 261 | 262 | ## Helpers 263 | 264 | ### `child_is_active` 265 | 266 | The child is active determines wether a list item has a child with an active 267 | route. The following example will add the `is-active` class when a list item has 268 | an active `route` that is added from route field. 269 | 270 | ```php 271 | $form->route('route_field')->collection('app')->title('Pick a route.'); 272 | ``` 273 | 274 | ```php 275 | @foreach($data->list as $item) 276 | 277 | {{ $item->title }} 278 | 279 | @endforeach 280 | ``` 281 | 282 | ## Customize Views 283 | 284 | If you want to customize the blade components, you can simply publish them and 285 | edit them as desired. 286 | 287 | ```shell 288 | php artisan vendor:publish --provider="Litstack\Bladesmith\BladesmithServiceProvider" --tag=views 289 | ``` 290 | -------------------------------------------------------------------------------- /packages/location.md: -------------------------------------------------------------------------------- 1 | # Location 2 | 3 | 4 | 5 | ## Introduction 6 | 7 | The location package ships with a google maps field that let's you benefit from 8 | the extensive places api, to search for location's or pick one from the map. 9 | 10 | ![maps](./screens/maps.png) 11 | 12 | ## Sponsorware 13 | 14 | Bladesmith was created by 15 | **[Lennart Carstens-Behrens](https://twitter.com/lennartcb)** under the 16 | **[Sponsorware license](https://github.com/sponsorware/docs)**. 17 | 18 | ::: tip 19 | 20 | [Sponsor litstack](https://github.com/sponsors/litstack) to get access to this 21 | package. 22 | 23 | ::: 24 | 25 | ## Setup 26 | 27 | Add the Litstack repository to your application's composer.json file: 28 | 29 | ```json 30 | "repositories": [ 31 | { 32 | "type": "composer", 33 | "url": "https://store.litstack.io" 34 | } 35 | ], 36 | ``` 37 | 38 | ```shell 39 | composer require litstack/location 40 | ``` 41 | 42 | ### Get A Google Api Key 43 | 44 | Now you need to get an api key to make use of google maps in your litstack 45 | project. 46 | 47 | - Go to the 48 | [Google credentials page](https://console.cloud.google.com/projectselector2/apis/credentials). 49 | - Create an Api Key. 50 | - Enable the following 51 | [libraries](https://console.cloud.google.com/apis/library) for your newly 52 | generated API Key 53 | ([Maps Javascript API](https://console.cloud.google.com/apis/library/maps-backend.googleapis.com), 54 | [Places API](https://console.cloud.google.com/apis/library/places-backend.googleapis.com)) 55 | 56 | The api key must now be added to your config under 57 | `lit.location.google_api_key`: 58 | 59 | ```php{config/lit.php} 60 | 'location' => [ 61 | 'google_api_key' => env('GOOGLE_MAPS_API_KEY'), 62 | ], 63 | ``` 64 | 65 | ## Maps Field 66 | 67 | The maps field let's the user pick location by searching for it or clicking 68 | somewhere on the map. 69 | 70 | The map field requires 2 parameters, the first one is the name of the latitude 71 | attribute, the second parameter is the longitude attribute name. 72 | 73 | ```php 74 | $form->map('lat', 'lng'); 75 | ``` 76 | 77 | ### Store Place Attributes 78 | 79 | The maps field let's you store additional information about places to your 80 | Model. This can be achieved by passing an array as a third parameter to the maps 81 | field, containing the desired attributes and the database column in which the 82 | attribute should be stored. In the following example the `formatted_address` 83 | would be stored in the `street` column. 84 | 85 | ```php 86 | $form->map('lat', 'lng', [ 87 | 'formatted_address' => 'street', 88 | ]); 89 | ``` 90 | 91 | The following attributes are available: 92 | 93 | | Method | Description | 94 | | ------------------- | ----------------------------- | 95 | | `formatted_address` | The formatted address name. | 96 | | `street_number` | The location's street number. | 97 | | `street_name` | The location's street name. | 98 | | `state` | The location's state. | 99 | | `city` | The location's city name. | 100 | | `country` | The location's country. | 101 | | `postal_code` | The location's postal code. | 102 | -------------------------------------------------------------------------------- /packages/meta.md: -------------------------------------------------------------------------------- 1 | # Meta 2 | 3 | ## Introduction 4 | 5 | A package to easily add meta for crud models and forms to your page. 6 | 7 | ## Installation 8 | 9 | The package can be installed via composer and will autoregister. 10 | 11 | ```bash 12 | composer require litstack/meta 13 | ``` 14 | 15 | You can now publish and migrate the migration for your meta model: 16 | 17 | ```shell 18 | php artisan vendor:publish --provider="Litstack\Meta\MetaServiceProvider" --tag=migrations 19 | php artisan migrate 20 | ``` 21 | 22 | ## Usage 23 | 24 | Start by preparing your Model by using the `HasMeta` Trait and implement the 25 | `metaable` Contract: 26 | 27 | ```php 28 | use Litstack\Meta\Metaable; 29 | use Litstack\Meta\Traits\HasMeta; 30 | 31 | class Post extends Model implements Metaable 32 | { 33 | use HasMeta; 34 | } 35 | ``` 36 | 37 | > Forms don't need further setup 38 | 39 | In order to display the form in litstack edit your model-config: 40 | 41 | ```php 42 | use Litstack\Meta\Traits\CrudHasMeta; 43 | 44 | class PostConfig extends CrudConfig 45 | { 46 | use CrudHasMeta; 47 | 48 | // … 49 | 50 | public function show(CrudShow $page) 51 | { 52 | $this->meta($page); 53 | } 54 | } 55 | ``` 56 | 57 | You may disable certain fields in the meta modal: 58 | 59 | ```php 60 | $this->meta($page, disable: [ 61 | 'description', 62 | 'keywords' 63 | ]); 64 | ``` 65 | 66 | To display the meta-fields in your template, simply use the `` 67 | component and pass it the `metaFields` of your model. 68 | 69 | ```php 70 | 71 | ... 72 | 73 | ... 74 | 75 | ``` 76 | 77 | ## Default Values / Customizing / Overriding 78 | -------------------------------------------------------------------------------- /packages/pages.md: -------------------------------------------------------------------------------- 1 | # Pages 2 | 3 | 4 | 5 | ## Introduction 6 | 7 | A package to turn your litstack application into a **CMS**. Add new pages to 8 | your application via the litstack interface. 9 | 10 | ![pages](./screens/pages_screen.jpg 'pages') 11 | 12 | ## Sponsorware 13 | 14 | Litstack pages was created by 15 | **[Lennart Carstens-Behrens](https://twitter.com/lennartcb)** under the 16 | **[Sponsorware license](https://github.com/sponsorware/docs)**. 17 | 18 | ## Setup 19 | 20 | Add the Litstack repository to your application's composer.json file: 21 | 22 | ```json 23 | "repositories": [ 24 | { 25 | "type": "composer", 26 | "url": "https://store.litstack.io" 27 | } 28 | ], 29 | ``` 30 | 31 | Install the package via composer: 32 | 33 | ```shell 34 | composer require litstack/pages 35 | ``` 36 | 37 | Publish the migrations and migrate: 38 | 39 | ```shell 40 | php artisan vendor:publish --provider="Litstack\Pages\PagesServiceProvider" 41 | 42 | php artisan migrate 43 | ``` 44 | 45 | ## Setup a pages collection 46 | 47 | With the artisan command lit:pages a new pages collection is created. For 48 | example `blog`: 49 | 50 | ```shell 51 | php artisan lit:pages Blog 52 | ``` 53 | 54 | A config is created and two controllers, one for the backend in 55 | `./lit/app/Controllers/Pages` and one for your application in 56 | `./app/Http/Controllers/Pages`. 57 | 58 | In the config you can configure the route prefix and the possible repeatables. 59 | The url of the page consists of the route prefix specified in the config and the 60 | sluggified page title. So a route for the following case could be 61 | `/blog/my-title`. If the page is translatable a route is created for each locale 62 | specified in the config like so: 63 | 64 | - `en/blog/{slug}` 65 | - `en/blog/{slug}` 66 | 67 | ```php{lit/app/Config/Pages/BlogConfig.php} 68 | class BlogConfig extends PagesConfig 69 | { 70 | ... 71 | 72 | public function appRoutePrefix(string $locale = null) 73 | { 74 | return "blog"; 75 | } 76 | 77 | public function repeatables(Repeatables $rep) 78 | { 79 | // Build your repeatables in here. 80 | } 81 | } 82 | ``` 83 | 84 | In the controller the page model is loaded with the method `getFjordPage`. This 85 | can now be passed to a view like this: 86 | 87 | ```php{app/Http/Controllers/Pages} 88 | use Litstack\Pages\ManagesPages; 89 | use Illuminate\Http\Request; 90 | 91 | class PagesController 92 | { 93 | use ManagesPages; 94 | 95 | public function __invoke(Request $request, $slug) 96 | { 97 | $page = $this->getFjordPage($slug); 98 | 99 | return view('pages.blog')->withPage($page); 100 | } 101 | } 102 | ``` 103 | 104 | ## Route Field 105 | 106 | To be able to select the pages in a route field you must first add them to a 107 | route collection as described in the 108 | [route field](../fields/route.md#register-routes) documentation. 109 | 110 | FjordPages extends to Eloquent Collection with the helper method 111 | `addToRouteCollection` that lets you add a list of pages directly to a route 112 | collection: 113 | 114 | ```php 115 | use Ignite\Crud\Fields\Route; 116 | use Litstack\Pages\Models\Page; 117 | 118 | Route::register('app', function($collection) { 119 | Page::collection('blog')->get()->addToRouteCollection('Blog', $collection); 120 | }); 121 | ``` 122 | -------------------------------------------------------------------------------- /packages/rehearsal.md: -------------------------------------------------------------------------------- 1 | # Rehearsal 2 | 3 | ## Introduction 4 | 5 | An [orchestra](https://github.com/orchestral/testbench) extension to simplify 6 | testing packages in a litstack application environment. 7 | 8 | ## Installation 9 | 10 | Install the package via composer: 11 | 12 | ```shell 13 | composer require --dev litstack/rehearsal 14 | ``` 15 | 16 | ## Usage 17 | 18 | To run tests in a litstack environment, your test class only needs to extend 19 | `Litstack\Rehearsal\TestCase`. 20 | 21 | ```php 22 | use Litstack\Rehearsal\TestCase as LitstackTestCase; 23 | 24 | class TestCase extends LitstackTestCase 25 | { 26 | public function test_litstack_is_installed() 27 | { 28 | $this->assertTrue(lit()->installed()); 29 | } 30 | } 31 | ``` 32 | 33 | This testcase is an extension of `Orchestra\Testbench\TestCase`. All its 34 | functions can be used. Read more on how to test your packages in the 35 | [orchestra docs](https://github.com/orchestral/testbench) 36 | -------------------------------------------------------------------------------- /packages/screens/lazy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/packages/screens/lazy.png -------------------------------------------------------------------------------- /packages/screens/maps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/packages/screens/maps.png -------------------------------------------------------------------------------- /packages/screens/nav-field.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/packages/screens/nav-field.png -------------------------------------------------------------------------------- /packages/screens/nav-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/packages/screens/nav-result.png -------------------------------------------------------------------------------- /packages/screens/pages_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/packages/screens/pages_screen.jpg -------------------------------------------------------------------------------- /packages/screens/verify.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/packages/screens/verify.gif -------------------------------------------------------------------------------- /prologue/about.md: -------------------------------------------------------------------------------- 1 | # About Litstack 2 | 3 | ## Who Are We 4 | 5 |
6 |
7 | 8 |
Jannes
Behrens
9 |
10 |
11 | 12 |
Lennart
Carstens-Behrens
13 |
14 |
15 | 16 | Hello there! We are very happy that you are stopping by. **We** are Jannes 17 | Behrens and Lennart Carstens-Behrens, two cousins from northern Germany who work 18 | together at the [Alle Wetter](https://aw-studio.de) Studio for Design and 19 | Development. We are passionate developers and have been working together for 20 | years on hobby projects and continued our collaboration shortly after Jannes and 21 | Gerrit founded Alle Wetter in 2016. The artwork is made by our experienced 22 | designer (Head of design at Alle Wetter) Uwe Steffens. Grüße an dich Uwe! 23 | 24 | ## How It Started 25 | 26 | In the middle of 2018 we thought for the first time about building our own cms. 27 | Requirements in projects became more complex and none of the existing systems 28 | offered a satisfactory solution. At that time we couldn't have imagined what 29 | would be develope from this idea now two years later: **litstack**. Along the 30 | way, we tried things out, rejected ideas and looked for the best ways to create 31 | a system that would meet both, developer & user experience: A clear and 32 | appealing user interface and a beginner-friendly yet powerful backend. The love 33 | for detail also cost a lot of time and nightly sessions. But we are more than 34 | happy with what has come out of it and that we can contribute to the 35 | **Open-Source** world with this project. 36 | 37 | On our way we always found immediate application in customer projects and the 38 | positive feedback motivated us in continuing our work. 39 | 40 | ### From CMS to Admin Panel 41 | 42 | After some time the idea of a **cms** changed to an **admin panel**, which has 43 | the possibility to perform the task of a cms. The management of data is the main 44 | problem to be solved in a modern web app. Be it an **API** or **internal product 45 | managing**. Everything is covered by an administration panel. 46 | 47 | ## Our Goal 48 | 49 | With litstack we try to simplify our life as developers, since we use it daily 50 | and continuously change or improve things due to our customers needs. 51 | Additionally we want to provide an attractive frontend that is not only clear 52 | but also fun to use. 53 | 54 | ### Backend 55 | 56 | #### Headless 57 | 58 | Our main goal is to provide a headless system that can be integrated into 59 | existing systems and above all does not make your project dependent on us. 60 | 61 | #### DX 62 | 63 | Our great example for the goals we pursue for the litstack backend is the 64 | [Laravel framework](https://laravel.com). Beginner-friendly yet powerful and 65 | easy to extend in all possible directions. All in a way that can be managed well 66 | and for a long time through clean architecture & code. 67 | 68 | ### Frontend 69 | 70 | There are many systems that have an overhead of things that most users rarely 71 | need. We want to make it easy to build a navigation system that lets the user 72 | find the important components of his application immediately: A scalable 73 | Interface where A baker who changes the title of his site once a month as well 74 | as the administrator of complex booking systems can easily find their way 75 | around. A logical and clear placement of the components on a clean surface. 76 | -------------------------------------------------------------------------------- /prologue/art.md: -------------------------------------------------------------------------------- 1 | # Artwork 2 | 3 | ## Introduction 4 | 5 | The artwork is made by **Uwe Steffen**, Head of Design at 6 | [Alle Wetter](https://aw-studio.de) Studio for Design and Development. You can 7 | find the logo and sketch files in the 8 | [litstack/art](https://github.com/litstack/art) repository. 9 | 10 | ![Logo Colors](./screens/logo-colors.jpeg 'Logo Colors') 11 | 12 | ![Logo Colors](./screens/iter-font.jpeg 'Logo Colors') 13 | 14 | ![Logo Colors](./screens/elements.jpeg 'Logo Colors') 15 | -------------------------------------------------------------------------------- /prologue/contribution.md: -------------------------------------------------------------------------------- 1 | # Contribution Guide 2 | 3 | ## Bug Reports 4 | 5 | To be able to track bug reports directly, we recommends pull-request before 6 | posting in the issue tracker. If you have difficulties reproducing the bug for a 7 | pull request, issue reports are of course welcome. 8 | 9 | ## Support Questions 10 | 11 | The GitHub issue tracker is reserved for bugs reports or feature requests. If 12 | you have questions, feel free to post them on 13 | [stackoverflow](https://stackoverflow.com/) or our 14 | [discord chanel](https://discord.gg/u4qpb5P). 15 | 16 | ::: tip 17 | 18 | Please keep in mind that the community will benefit if a **solved problem** can 19 | be found via google on stackoverflow. 20 | 21 | ::: 22 | 23 | ## Compiled Assets 24 | 25 | If you are submitting a change that will affect a compiled file, such as most of 26 | the files in `resources/sass` or `resources/js` of any litstack repository, do 27 | not commit the compiled files. Due to their large size, they cannot 28 | realistically be reviewed by a maintainer. This could be exploited as a way to 29 | inject malicious code into Litstack. In order to defensively prevent this, all 30 | compiled files will be generated and committed by Litstack maintainers. 31 | 32 | ## Security Vulnerabilities 33 | 34 | If you discover a security vulnerability within Litstack, please send an email 35 | to Lennart Carstens-Behrens at lennart.carbe@gmail.com or Jannes Behrens at 36 | jannes@aw-studio.de. All security vulnerabilities will be promptly addressed. 37 | 38 | ## Coding Style 39 | 40 | Litstack follows the PSR-2 coding standard as laravel. The 41 | [Style CI](https://styleci.io/) included in the repository uses the 42 | [laravel preset](https://docs.styleci.io/presets#laravel) to keep the code in a 43 | familiar laravel standard. 44 | 45 | ::: tip 46 | 47 | Checkout an example of an example of a laravel PHPDoc on the 48 | [laravel website](https://laravel.com/docs/7.x/contributions#phpdoc). 49 | 50 | ::: 51 | 52 | ### PHP CS Fixer 53 | 54 | Litstack uses a [PHP CS Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) 55 | config whose goal is to closely match the coding standard of laravel. The fixer 56 | can be executed with the following composer command. 57 | 58 | ```shell 59 | composer style 60 | ``` 61 | 62 | ## Testing 63 | 64 | Tests are divided into two parts. `PHP` tests for the backend via 65 | [PHPUnit](https://phpunit.readthedocs.io/en/9.2/) and `Javascript` test for the 66 | frontend via [Jest](https://jestjs.io/). Depending on what you are working on 67 | you may only want to test one part. 68 | 69 | Installing the test dependencies can be done by installing the composer and/or 70 | npm packages: 71 | 72 | ```shell 73 | composer install && npm install 74 | ``` 75 | 76 | ### PHP Tests 77 | 78 | Run the php tests via **composer**: 79 | 80 | ```shell 81 | composer test 82 | ``` 83 | 84 | Some tests require a chromedriver to be running on port `9515`. If you want to 85 | cover them as well before pushing to your repository you may start a 86 | chromedriver before: 87 | 88 | ```shell 89 | chromedriver --port=9515 90 | ``` 91 | 92 | ### Javascript Tests 93 | 94 | Run the javascript tests via **npm**: 95 | 96 | ```shell 97 | npm test:js 98 | ``` 99 | -------------------------------------------------------------------------------- /prologue/screens/cbl.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/prologue/screens/cbl.jpeg -------------------------------------------------------------------------------- /prologue/screens/elements.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/prologue/screens/elements.jpeg -------------------------------------------------------------------------------- /prologue/screens/iter-font.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/prologue/screens/iter-font.jpeg -------------------------------------------------------------------------------- /prologue/screens/jb.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/prologue/screens/jb.jpeg -------------------------------------------------------------------------------- /prologue/screens/logo-colors.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/litstack/docs/66b8e6f4ce6ec184127102dc63553cbad41a7b03/prologue/screens/logo-colors.jpeg -------------------------------------------------------------------------------- /prologue/sponsorware.md: -------------------------------------------------------------------------------- 1 | # Sponsorware 2 | 3 | ## Introduction 4 | 5 | Litstack is made available to the community as an open-source project. We are 6 | spending our free time to improve and maintain this project. Therefore we are 7 | very happy that you are considering supporting this through sponsoring. We also 8 | give something back for our sponsors. Extensive screencasts and helpfull 9 | additional package for litstack like bladesmith or pages. 10 | 11 | ## How it Works 12 | 13 | To get access to the sponsorware go to 14 | [github.com/sponsors/litstack](https://github.com/sponsors/litstack) and read 15 | the tier section on the right side. Select a tier to get access to the desired 16 | sponsorware. 17 | 18 | ### Screencasts 19 | 20 | To get access to the screencasts go to 21 | [litstack.io/screencasts](https://litstack.io/screencasts) and log in with your 22 | github account. You will then be shown the sponsorware videos. 23 | 24 | ### Packages 25 | 26 | To get access to the packages bladesmith and pages you can send an email to 27 | `lennart.carbe@gmail.com`. Lennart will then send you an access token to install 28 | the private composer packages. 29 | -------------------------------------------------------------------------------- /prologue/upgrade.md: -------------------------------------------------------------------------------- 1 | # Upgrade Guide 2 | 3 | ## Upgrading from 2.4 to 3.x 4 | 5 | Due to a trademark dispute, the name used in version 2.4 for this package had to 6 | be changed. Considering the fact that this will cause big breaking changes, we 7 | have decided to make significant changes in the architecture. Unfortunately this 8 | also means that we cannot provide an upgrade guide. However you are free to 9 | develop your own solution and if possible make it available to the community. 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Litstack Documentation 2 | 3 | The online version of the documentation can be reached under 4 | [https://litstack.io/docs](https://litstack.io/docs) 5 | 6 | ## Index 7 | 8 | - ## Prologue 9 | - [About](prologue/about.md) 10 | - [Artwork](prologue/art.md) 11 | - [Upgrade Guide](prologue/upgrade.md) 12 | - [Contribution](prologue/contribution.md) 13 | - [Sponsorware](prologue/sponsorware.md) 14 | - ## Getting Started 15 | - [Installation](installation.md) 16 | - [Configuration](configuration.md) 17 | - ## Basics 18 | - [Basics](basics.md) 19 | - [Navigation](basics/navigation.md) 20 | - [Page](basics/page.md) 21 | - [Localization](basics/localization.md) 22 | - [Helpers](basics/helpers.md) 23 | - ## CRUD 24 | - [Model](crud/model.md) 25 | - [Forms](crud/forms.md) 26 | - [Index Config](crud/index.md) 27 | - [Show Config](crud/show.md) 28 | - [Table](crud/table.md) 29 | - [Actions](crud/actions.md) 30 | - [Search](crud/search.md) 31 | - ## Fields 32 | - [Introduction](fields/introduction.md) 33 | - [Block](fields/block.md) 34 | - [Boolean](fields/boolean.md) 35 | - [Checkboxes](fields/checkboxes.md) 36 | - [Date/Time](fields/date-time.md) 37 | - [Icon](fields/icon.md) 38 | - [Image](fields/image.md) 39 | - [Input](fields/input.md) 40 | - [List](fields/list.md) 41 | - [Modal](fields/modal.md) 42 | - [Password](fields/password.md) 43 | - [Radio](fields/radio.md) 44 | - [Range](fields/range.md) 45 | - [Relation](fields/relation.md) 46 | - [Route](fields/route.md) 47 | - [Select](fields/select.md) 48 | - [Textarea](fields/textarea.md) 49 | - [WYSIWYG](fields/wysiwyg.md) 50 | - [Validation](fields/validation.md) 51 | - [Conditional Fields](fields/conditions.md) 52 | - [Masks](fields/masks.md) 53 | - ## Charts 54 | - [Basics](charts/basics.md) 55 | - [Area Chart](charts/area.md) 56 | - [Bar Chart](charts/bar.md) 57 | - [Number](charts/number.md) 58 | - [Donut Chart](charts/donut.md) 59 | - [Progress](charts/progress.md) 60 | - ## Frontend 61 | - [Javascript](frontend/javascript.md) 62 | - [Vue](frontend/vue.md) 63 | - ## Official Packages 64 | - [Location / Maps](packages/location.md) 65 | - [Meta](packages/meta.md) 66 | - [Bladesmith](packages/bladesmith.md) 67 | - [Pages](packages/pages.md) 68 | - [2 Factor Authentication](packages/2fa.md) 69 | - [Rehearsal](packages/rehearsal.md) 70 | --------------------------------------------------------------------------------