├── .gitignore ├── README.md ├── composer.json ├── composer.lock ├── icon.png ├── imgs ├── Klaravel.sketch ├── klaravel.png ├── klaravel.svg ├── logo.svg ├── v2-component.png ├── v2-dashboard.png ├── v2-logs.png ├── v2-routes.png ├── v2-scaffold.png └── v2-traits.png ├── package.json ├── release.sh ├── resources ├── _kLara │ ├── _parts │ │ ├── _scripts.blade.php │ │ ├── _styles.blade.php │ │ └── wiki-tabs.blade.php │ ├── comming-soon.blade.php │ ├── dashboard.blade.php │ ├── modules │ │ └── krud.blade.php │ ├── panels │ │ ├── components.blade.php │ │ ├── dashboard.blade.php │ │ ├── helpers.blade.php │ │ ├── layouts.blade.php │ │ ├── scaffold.blade.php │ │ ├── traits.blade.php │ │ └── utils.blade.php │ └── wiki.blade.php ├── _parts │ ├── analytics.blade.php │ ├── footer.blade.php │ ├── header.blade.php │ ├── header_menu.blade.php │ ├── menu │ │ ├── custom.blade.php │ │ ├── klara.blade.php │ │ ├── settings.blade.php │ │ └── user_dropdown.blade.php │ └── no-records.blade.php ├── admin │ ├── activitylog-table.blade.php │ ├── activitylog.blade.php │ ├── backups-table.blade.php │ ├── backups.blade.php │ ├── cache-table.blade.php │ ├── cache.blade.php │ ├── plugins.blade.php │ ├── routes-table.blade.php │ ├── routes.blade.php │ ├── sessions-table.blade.php │ └── sessions.blade.php ├── assets │ ├── js │ │ ├── components │ │ │ ├── ElementDate.vue │ │ │ ├── ElementRange.vue │ │ │ ├── ElementSelect.vue │ │ │ └── ElementUpload.vue │ │ └── klaravel.js │ └── sass │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.scss │ │ ├── bt4.css │ │ ├── bt4.css.map │ │ ├── bt4.scss │ │ ├── footer.scss │ │ ├── heart.scss │ │ ├── klara.scss │ │ ├── markdown.scss │ │ ├── stars.scss │ │ └── tables.scss ├── crud │ ├── create.blade.php │ ├── edit.blade.php │ └── index.blade.php ├── layouts │ ├── app.blade.php │ └── crud.blade.php └── ui │ ├── alert.blade.php │ ├── badge.blade.php │ ├── button-group.blade.php │ ├── card-deck-media.blade.php │ ├── card.blade.php │ ├── carousel.blade.php │ ├── dropdown.blade.php │ ├── errors.blade.php │ ├── figure.blade.php │ ├── forms │ ├── buttons.blade.php │ ├── radios.blade.php │ └── textarea.blade.php │ ├── list-group.blade.php │ ├── map │ └── script.blade.php │ ├── menu-nav.blade.php │ ├── modal.blade.php │ ├── nav.blade.php │ ├── tab.blade.php │ └── tables │ ├── actions-menu.blade.php │ ├── actions.blade.php │ ├── booble.blade.php │ ├── btn-delete.blade.php │ ├── count-query.blade.php │ ├── count.blade.php │ ├── media_info.blade.php │ ├── order.blade.php │ ├── pagination.blade.php │ ├── sort-dropdown.blade.php │ └── truncate.blade.php ├── src ├── Console │ ├── Commands │ │ ├── InstallPlugin.php │ │ ├── MakeKrud.php │ │ └── PublishConfig.php │ ├── Helpers │ │ ├── GeneratorField.php │ │ ├── GeneratorFieldRelation.php │ │ ├── Publisher.php │ │ ├── TableFieldsGenerator.php │ │ └── helpers.php │ └── plugins │ │ ├── composer_install.sh │ │ └── test.sh ├── Contracts │ └── EloquentRepoContract.php ├── DirectivesProvider.php ├── Facade.php ├── Http │ ├── Controllers │ │ ├── ActivitylogController.php │ │ ├── BackupController.php │ │ ├── CacheController.php │ │ ├── Controller.php │ │ ├── CrudController.php │ │ ├── KlaravelController.php │ │ ├── PluginsController.php │ │ ├── SessionController.php │ │ └── UtilsController.php │ └── routes.php ├── Larapp.php ├── Middleware │ └── Throttle.php ├── Models │ ├── Cache.php │ └── Session.php ├── Repositories │ └── EloquentRepo.php ├── Routing │ └── KrudPolicyController.php ├── ServiceProvider.php ├── Traits │ ├── ActiveScope.php │ ├── CallsInteractions.php │ ├── CanChangeStatuses.php │ ├── CanSortRecords.php │ ├── CanUploadMedia.php │ ├── HasLogs.php │ ├── JsonTrait.php │ ├── KrudControllerTrait.php │ ├── LumenResponsesTrait.php │ ├── QueryFiltersTrait.php │ ├── UserModelOptions.php │ └── ValidateInteraction.php ├── Utils │ ├── FormerBootstrap4.php │ ├── InstPlugins.php │ └── JsonResponse.php └── helpers.php ├── stubs ├── Contracts │ ├── ExampleCreate.php │ ├── ExampleRepository.php │ └── ExampleUpdate.php ├── Controllers │ ├── BaseCtrl.php │ ├── BaseKrudController.php │ └── ExampleController.php ├── DataTables │ └── ExampleDataTable.php ├── Interactions │ ├── ExampleCreate.php │ └── ExampleUpdate.php ├── Repositories │ └── ExampleRepository.php ├── config │ ├── ksoft.php │ └── settings │ │ ├── contact.php │ │ ├── forms.php │ │ ├── maps.php │ │ └── social.php ├── krud │ ├── create.blade.php │ ├── edit.blade.php │ ├── form.blade.php │ ├── index.blade.php │ └── table.blade.php ├── routes │ ├── crud.stub │ └── resource.stub └── swagger │ ├── controller.stub │ └── property.stub └── wiki ├── README.md ├── components-maps.md ├── components-tables.md ├── components-vue.md ├── components-widgets.md ├── formers.md ├── helpers-backups.md ├── helpers-commons.md ├── helpers-config.md ├── helpers-functions.md ├── helpers-mailables.md ├── helpers-passport.md ├── helpers-seeds.md ├── helpers-seo.md ├── helpers-sortable.md ├── helpers-tags.md ├── helpers-translatable.md ├── helpers-translate.md ├── helpers-validations.md ├── krud-help.md ├── krud-policy.md ├── krud-views.md ├── layouts-footer.md ├── layouts-header.md ├── layouts-menu.md ├── layouts-settings.md ├── trait-controllers.md ├── trait-eloquent.md ├── trait-models.md ├── trait-repositories.md └── trait-responses.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | .DS_Store 3 | /node_modules/ 4 | yarn* 5 | .sass-cache 6 | /.gtm/ 7 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ksoft/klaravel", 3 | "description": "Laravel control panel for developers, comes with integrated Scaffold generator, backups, logs, and built in instructions.", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Kiko Seijo", 9 | "email": "kiko@sunnyface.com" 10 | } 11 | ], 12 | "autoload": { 13 | "psr-4": { 14 | "Ksoft\\Klaravel\\": "src/" 15 | }, 16 | "files": [ 17 | "src/helpers.php" 18 | ] 19 | }, 20 | "config": { 21 | "sort-packages": true 22 | }, 23 | "require": { 24 | "anahkiasen/former": "^4.6", 25 | "league/commonmark": "^1.5", 26 | "spatie/laravel-activitylog": "^3.2", 27 | "spatie/laravel-backup": "^6.2" 28 | }, 29 | "require-dev": { 30 | "laravel/laravel": "5.8.*", 31 | "laravel/lumen": "5.8.*" 32 | }, 33 | "extra": { 34 | "laravel": { 35 | "providers": [ 36 | "Ksoft\\Klaravel\\ServiceProvider" 37 | ], 38 | "aliases": { 39 | "Larapp": "Ksoft\\Klaravel\\Facade" 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikoseijo/klaravel/7c84f74561da266fa23ab86cd137a7fcf946823d/icon.png -------------------------------------------------------------------------------- /imgs/Klaravel.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikoseijo/klaravel/7c84f74561da266fa23ab86cd137a7fcf946823d/imgs/Klaravel.sketch -------------------------------------------------------------------------------- /imgs/klaravel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikoseijo/klaravel/7c84f74561da266fa23ab86cd137a7fcf946823d/imgs/klaravel.png -------------------------------------------------------------------------------- /imgs/klaravel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /imgs/v2-component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikoseijo/klaravel/7c84f74561da266fa23ab86cd137a7fcf946823d/imgs/v2-component.png -------------------------------------------------------------------------------- /imgs/v2-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikoseijo/klaravel/7c84f74561da266fa23ab86cd137a7fcf946823d/imgs/v2-dashboard.png -------------------------------------------------------------------------------- /imgs/v2-logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikoseijo/klaravel/7c84f74561da266fa23ab86cd137a7fcf946823d/imgs/v2-logs.png -------------------------------------------------------------------------------- /imgs/v2-routes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikoseijo/klaravel/7c84f74561da266fa23ab86cd137a7fcf946823d/imgs/v2-routes.png -------------------------------------------------------------------------------- /imgs/v2-scaffold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikoseijo/klaravel/7c84f74561da266fa23ab86cd137a7fcf946823d/imgs/v2-scaffold.png -------------------------------------------------------------------------------- /imgs/v2-traits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kikoseijo/klaravel/7c84f74561da266fa23ab86cd137a7fcf946823d/imgs/v2-traits.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "klaravel", 3 | "version": "v3.1.6", 4 | "description": "A personal set of Tools and Helpers for Laravel developers.", 5 | "main": "index.js", 6 | "scripts": { 7 | "watch": "sass --style compact --watch resources/assets/sass/bootstrap.scss", 8 | "build": "sass --style compact resources/assets/sass/bootstrap.scss" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/kikoseijo/kLaravel.git" 13 | }, 14 | "keywords": [ 15 | "laravel", 16 | "framework", 17 | "templates", 18 | "skeleton", 19 | "crud", 20 | "scaffold", 21 | "control", 22 | "panel", 23 | "admin", 24 | "panel" 25 | ], 26 | "author": "Kiko Seijo", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/kikoseijo/kLaravel/issues" 30 | }, 31 | "homepage": "https://github.com/kikoseijo/kLaravel#readme", 32 | "dependencies": { 33 | "bootstrap": "^4.0.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | #Fetch remote tags 4 | git fetch origin 'refs/tags/*:refs/tags/*' 5 | 6 | #Variables 7 | LAST_VERSION=$(git tag -l | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n | tail -n 1) 8 | NEXT_VERSION=$(echo $LAST_VERSION | awk -F. -v OFS=. 'NF==1{print ++$NF}; NF>1{if(length($NF+1)>length($NF))$(NF-1)++; $NF=sprintf("%0*d", length($NF), ($NF+1)%(10^length($NF))); print}') 9 | VERSION=${1-${NEXT_VERSION}} 10 | DEFAULT_MESSAGE="Release" 11 | MESSAGE=${2-${DEFAULT_MESSAGE}} 12 | RELEASE_BRANCH="release/$VERSION" 13 | 14 | # Commit uncommited changes 15 | git add . 16 | git commit -am $MESSAGE 17 | git push origin develop 18 | 19 | # Merge develop branch in master 20 | git checkout master 21 | git merge develop 22 | 23 | # Tag and push master 24 | git tag $VERSION 25 | git push origin master --tags 26 | 27 | # Return to develop 28 | git checkout develop 29 | -------------------------------------------------------------------------------- /resources/_kLara/_parts/_scripts.blade.php: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /resources/_kLara/_parts/_styles.blade.php: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /resources/_kLara/_parts/wiki-tabs.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 10 |
11 |
12 |
13 | @foreach ($mdMenu as $mdKey => $mdValue) 14 |
15 | {!! do_markdown(file_get_contents(KLARAVEL_PATH . '/wiki/'.$section.'-'.$mdKey.'.md')) !!} 16 |
17 | @endforeach 18 |
19 |
20 |
21 | -------------------------------------------------------------------------------- /resources/_kLara/comming-soon.blade.php: -------------------------------------------------------------------------------- 1 | @extends('klaravel::layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |

Comming soon..

7 |
8 | 9 |
10 | @endsection 11 | 12 | {{-- 13 | @push('stylesheets') 14 | 15 | @endpush 16 | 17 | @push('scripts') 18 | 19 | 20 | @endpush --}} 21 | -------------------------------------------------------------------------------- /resources/_kLara/modules/krud.blade.php: -------------------------------------------------------------------------------- 1 |

Generate new Scaffold

2 |

3 | Use this form to generate new krud, only requirement its the model name. Configure the output 4 | trought configuration file `config/ksoft.php`. 5 |

6 | 7 | {!! Former::horizontal_open()->route('kLara.krud.gen') !!} 8 | {!! Former::text('model_name')->required()->label('Model name')->placeholder('ej.: User') !!} 9 | {!! Former::text('base_path') 10 | ->label('Base path') 11 | ->placeholder('ej.: Backend') 12 | ->help('Path starts at App\Http\\') !!} 13 | 14 |
15 |
16 | 17 |
18 |
19 | {!! Former::close() !!} 20 | 21 | 22 |
23 | 24 |

Publish files

25 | 26 | 27 |

28 | You should only publish this files once ?? to update from an older version, 29 | you will loose any changes made to them if you overwrite them. 30 |

31 | 32 | 35 | Configuration 36 | 37 | 38 | 41 | BaseCtrl (v3) 42 | 43 | 44 | 47 | BaseKrudController 48 | 49 | 50 | 51 |
 
52 | -------------------------------------------------------------------------------- /resources/_kLara/panels/components.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 19 |
20 |
21 |
22 |
23 | {!! do_markdown(file_get_contents(KLARAVEL_PATH . '/wiki/components-tables.md')) !!} 24 |
25 |
26 | {!! do_markdown(file_get_contents(KLARAVEL_PATH . '/wiki/components-widgets.md')) !!} 27 |
28 |
29 | {!! do_markdown(file_get_contents(KLARAVEL_PATH . '/wiki/components-vue.md')) !!} 30 |
31 |
32 | {!! do_markdown(file_get_contents(KLARAVEL_PATH . '/wiki/components-maps.md')) !!} 33 |
34 |
35 |
36 |
37 | -------------------------------------------------------------------------------- /resources/_kLara/panels/dashboard.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 21 |
22 |
23 |
24 |
25 | @include('klaravel::_kLara.modules.krud') 26 | {!! do_markdown(file_get_contents(KLARAVEL_PATH . '/wiki/krud.md')) !!} 27 |
28 |
29 |

Krud base layout


30 | {!! do_markdown('```' .file_get_contents(KLARAVEL_PATH . '/resources/layouts/crud.blade.php').'```') !!} 31 |
32 |
33 | {!! do_markdown(file_get_contents(KLARAVEL_PATH . '/wiki/formers.md')) !!} 34 |
35 |
Settings
36 |
37 | @include('klaravel::_kLara.panels.utils') 38 | 39 |
40 |
41 |
42 |
43 | -------------------------------------------------------------------------------- /resources/_kLara/panels/layouts.blade.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/_kLara/panels/utils.blade.php: -------------------------------------------------------------------------------- 1 |
Dev Utils
2 |

3 | Common development trigger actions, under your responsability, of course. 4 |

5 | {{-- Clean Settings 6 | Flush Settings --}} 7 | Flush DB Cache 8 | Bugsnag error test 9 | Schedule Info 10 | -------------------------------------------------------------------------------- /resources/_kLara/wiki.blade.php: -------------------------------------------------------------------------------- 1 | @extends('klaravel::layouts.app') 2 | @php 3 | if ($section == 'layouts') { 4 | $mdMenu = [ 5 | 'header' => 'The Header', 6 | 'footer' => 'The Footer', 7 | 'menu' => 'Main menu', 8 | 'settings' => 'Settings menu', 9 | ]; 10 | } 11 | @endphp 12 | @section('content') 13 |
14 | @card(['title' => 'Wiki - ' . title_case($section), 'class' => 'mb-4']) 15 | @if (isset($mdMenu)) 16 | @include('klaravel::_kLara._parts.wiki-tabs',[ 17 | 'section' => $section, 18 | 'mdActiveKey' => 'header', 19 | 'mdMenu' => $mdMenu, 20 | ]) 21 | @else 22 | @include('klaravel::_kLara.panels.'.$section) 23 | @endif 24 | @endcard 25 |
26 | @endsection 27 | 28 | 29 | @push('stylesheets') 30 | 31 | @endpush 32 | 33 | @push('scripts') 34 | 35 | 36 | @endpush 37 | -------------------------------------------------------------------------------- /resources/_parts/analytics.blade.php: -------------------------------------------------------------------------------- 1 | @if (isset($anaKey) && $anaKey != '') 2 | 3 | 4 | 10 | @endif 11 | -------------------------------------------------------------------------------- /resources/_parts/footer.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @php 3 | $gitVersion = trim(exec('git log --pretty="%h" -n1 HEAD')); 4 | @endphp 5 | 40 | -------------------------------------------------------------------------------- /resources/_parts/header.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @php 3 | $d_route = config('ksoft.backend_dashboard_route_name'); 4 | $dashboard_url = $d_route != '' ? route($d_route) : url('/').'" target="_blank'; 5 | 6 | if ($admin_menu_location = config('ksoft.menu_admin_config_location')) { 7 | $admin_menu = config($admin_menu_location); 8 | } 9 | 10 | if ($settings_menu_location = config('ksoft.menu_settings_config_location')) { 11 | $settings_menu = config($settings_menu_location); 12 | } 13 | 14 | @endphp 15 | 34 | 35 | @if (count(config('ksoft.CONSTANTS')) == 0) 36 | @component('klaravel::ui.alert', [ 37 | 'title' => 'Alert title', 38 | 'type' => 'warning', 39 | 'class' => 'my-3 container', 40 | ]) 41 | Some files are missing , action required: 42 | Publish initial configuration 43 | @endcomponent 44 | @endif 45 | -------------------------------------------------------------------------------- /resources/_parts/header_menu.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @php 3 | $preroute = array_first(explode('.', $croute)); 4 | @endphp 5 | 23 | -------------------------------------------------------------------------------- /resources/_parts/menu/custom.blade.php: -------------------------------------------------------------------------------- 1 | @isset($admin_menu) 2 | 3 | 4 | @foreach ($admin_menu as $menuRoute => $menuLabel) 5 | @php 6 | $is_active_class = $croute == $menuRoute || in_array($preroute, explode('.',$menuRoute)) ? ' active':''; 7 | @endphp 8 | @if (is_array($menuLabel)) 9 | 10 | @if (count($menuLabel) == 1) 11 | @php 12 | $mLabel = collect($menuLabel)->keys()->first(); 13 | $singleLabel = str_contains($mLabel, 'fa-') ? '' : $mLabel; 14 | @endphp 15 | 23 | @else 24 | 25 | @component('klaravel::ui.dropdown', [ 26 | 'title' => $menuRoute, 27 | 'class' => ' mx-2 ', 28 | 'active' => array_key_exists($croute, array_keys($menuLabel)) 29 | ]) 30 | @foreach ($menuLabel as $subKey => $subValue) 31 | @php 32 | $selected = $menuRoute == $croute && request()->route('config_name') == $subKey ? ' active': ''; 33 | @endphp 34 | 35 | {{$subValue}} 36 | 37 | @endforeach 38 | @endcomponent 39 | 40 | @endif 41 | @else 42 | 47 | @endif 48 | @endforeach 49 | @endisset 50 | -------------------------------------------------------------------------------- /resources/_parts/menu/klara.blade.php: -------------------------------------------------------------------------------- 1 | @if (config('ksoft.klaravel_enabled')) 2 | 3 | @php 4 | $kAdmins = config('ksoft.klaravel_visible_for'); 5 | @endphp 6 | @if (!is_array($kAdmins) || count($kAdmins) == 0 || (count($kAdmins) > 0 && in_array(auth()->id(), $kAdmins))) 7 | 17 | @endif 18 | @endif 19 | -------------------------------------------------------------------------------- /resources/_parts/menu/settings.blade.php: -------------------------------------------------------------------------------- 1 | @if(isset($settings_menu) && isset($settings_menu_enabled)) 2 | 3 | @if ($settings_menu_enabled) 4 | @foreach ($settings_menu as $menuTitle => $menuItems) 5 | @if (is_array($menuItems)) 6 | @component('klaravel::ui.dropdown', [ 7 | 'title' => $menuTitle, 8 | 'active' => is_array($menuItems) && array_key_exists($croute, $menuItems) 9 | ]) 10 | @foreach ($menuItems as $setUrl => $setLabel) 11 | {{ $setLabel }} 12 | @endforeach 13 | @endcomponent 14 | @else 15 | 20 | @endif 21 | @endforeach 22 | @endif 23 | @else 24 | @if (config('ksoft.show_integration_hints')) 25 | 26 | 31 | @endif 32 | @endif 33 | -------------------------------------------------------------------------------- /resources/_parts/menu/user_dropdown.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @component('klaravel::ui.dropdown', [ 3 | 'title' => ' ', 4 | 'active' => 'ksoft' == $preroute || in_array($croute, ['kSessions', 'kLogs', 'kCache', 'kBackup']) 5 | ]) 6 | @if (config('ksoft.enable_plugins_menu')) 7 | Install plugin 8 | @endif 9 | @if (config('ksoft.module.activity_log.enabled')) 10 | Activity Logs 11 | @endif 12 | @if (config('ksoft.module.sessions.enabled')) 13 | DB Sessions 14 | @endif 15 | @if (config('ksoft.module.caches.enabled')) 16 | DB Cache 17 | @endif 18 | @if (config('ksoft.module.backup.enabled')) 19 | Backups 20 | @endif 21 | 22 | @if (Route::has('login')) 23 | 25 | Logout    26 | 27 | 30 | @endif 31 | @endcomponent 32 | -------------------------------------------------------------------------------- /resources/_parts/no-records.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |

No {{ $records_name ?? 'records'}} found

4 |
5 | -------------------------------------------------------------------------------- /resources/admin/activitylog-table.blade.php: -------------------------------------------------------------------------------- 1 | @isset($iLogs) 2 | @if(count($iLogs)) 3 | 4 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | @foreach($iLogs as $logItem) 22 | 23 | 24 | 25 | 26 | 27 | 32 | 39 | 40 | 41 | 44 | 45 | @endforeach 46 | 47 |
5 | @includeIf('klaravel::ui.tables.count',[ 6 | 'class' => 'text-muted', 7 | 'records' => $iLogs 8 | ]) 9 |
TypeModelDateActivityUser
{!! $logItem->log_name !!}{!! isset($logItem->subject_type) ? model_title($logItem->subject_type) :'-' !!}{{ $logItem->created_at->diffForHumans() }}{!! $logItem->description !!} 28 | @if($logItem->causer) 29 | {{ $logItem->causer->name }} 30 | @endif 31 | 33 | @component('klaravel::ui.button-group',['class' => 'btn-group-sm']) 34 | 35 | 36 | 37 | @endcomponent 38 |
42 | @json($logItem) 43 |
48 | @else 49 | @includeif('klaravel::_parts.no-records', ['recrods_name' => 'Activity logs']) 50 | @endif 51 | @endisset 52 | -------------------------------------------------------------------------------- /resources/admin/backups-table.blade.php: -------------------------------------------------------------------------------- 1 | @if (count($backups)) 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | @foreach($backups as $backup) 13 | 14 | 18 | 19 | 20 | 21 | 32 | 33 | @endforeach 34 | 35 |
DateFileSize
15 | {{ date('d M Y, g:ia', strtotime($backup['last_modified'])) }} 16 | ({{ diff_string_for_humans($backup['last_modified']) }}) 17 | {{ $backup['file_name'] }}{{ $backup['file_size'] }} 22 | 31 |
36 | @else 37 | @includeif('klaravel::_parts.no-records', ['recrods_name' => 'backups']) 38 | @endif 39 | -------------------------------------------------------------------------------- /resources/admin/backups.blade.php: -------------------------------------------------------------------------------- 1 | @php 2 | $title = 'Backups (db + filesystem)'; 3 | @endphp 4 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 5 | 6 | @section('content') 7 |
8 | @card(['title' => 'Backups', 'reload_btn' => true]) 9 | @component('klaravel::ui.menu-nav') 10 | 15 | @if (config('ksoft.module.backup.can_see_full_backups')) 16 | 24 | @endif 25 | 26 | 27 | @endcomponent 28 |
29 | @includeIf('klaravel::admin.backups-table') 30 |
31 | @endcard 32 |
33 | @endsection 34 | -------------------------------------------------------------------------------- /resources/admin/cache-table.blade.php: -------------------------------------------------------------------------------- 1 | @isset($records) 2 | @if(count($records)) 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | @foreach($records as $record) 14 | @php 15 | $cacheKey = str_replace(config('cache.prefix'), '', $record->key); 16 | @endphp 17 | 18 | 19 | 20 | 25 | 26 | 27 | 30 | 31 | @endforeach 32 | 33 |
@includeIf('klaravel::ui.tables.count')
Expire dateKey
{{ diff_date_for_humans(($record->expiration)) }}{{ $record->key }} 21 | 22 | 23 | 24 |
28 | {!! json_encode(cache($cacheKey)) !!} 29 |
34 | {{-- 35 | Ver todos los logs de actividad 36 | --}} 37 | @else 38 | @includeif('klaravel::_parts.no-records') 39 | 40 | @endif 41 | @endisset 42 | -------------------------------------------------------------------------------- /resources/admin/cache.blade.php: -------------------------------------------------------------------------------- 1 | @php 2 | $title = 'Caché configuration'; 3 | @endphp 4 | 5 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 6 | 7 | @section('content') 8 |
9 | @card(['title' => 'Cache table', 'reload_btn' => true]) 10 | 13 |
14 | @includeIf('klaravel::admin.cache-table') 15 |
16 | 17 | @endcard 18 |
19 | @endsection 20 | -------------------------------------------------------------------------------- /resources/admin/plugins.blade.php: -------------------------------------------------------------------------------- 1 | @php 2 | $title = 'Plugins (kLaravel)'; 3 | @endphp 4 | 5 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 6 | 7 | @section('content') 8 | 9 |
10 | @component('klaravel::ui.alert', [ 11 | 'type' => 'danger', 12 | ]) 13 | This section its not working right now, check back soon... 14 | @endcomponent 15 |
16 | 17 |
18 | @foreach ($plugins as $key => $plugin) 19 | @card([ 20 | 'title' => $plugin['name'], 21 | 'style' => 'width: 26rem;' 22 | ]) 23 |

24 | For more info please visit:
25 | 26 | {!! $plugin['help_url'] !!} 27 | 28 |

29 | @if (!class_exists($plugin['main_class'])) 30 | 31 | Install plugin 32 | 33 | @else 34 | 35 | Uninstall plugin 36 | 37 | 38 | @endif 39 | @endcard 40 | @endforeach 41 |
42 | @endsection 43 | -------------------------------------------------------------------------------- /resources/admin/routes-table.blade.php: -------------------------------------------------------------------------------- 1 | @if (count($routes)) 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | @php 15 | $methods = [ 16 | 'WILD' => 'GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS', 17 | 'GET' => 'GET|HEAD', 18 | 'PUT' => 'PUT|PATCH', 19 | ]; 20 | @endphp 21 | @foreach($routes as $route) 22 | @php 23 | $middleware = array_get($route, 'middleware'); 24 | $action = array_get($route, 'action'); 25 | $action_value = str_replace(array_values($methods), array_keys($methods), $route['method']); 26 | $action_color = $action_value == 'GET' ? 'success' : 27 | ($action_value == 'POST' ? 'warning' : 28 | ($action_value == 'WILD' ? 'primary' : 'danger')); 29 | $route_name = array_get($route, 'name'); 30 | 31 | 32 | @endphp 33 | 34 | 35 | 36 | 41 | 42 | 43 | 65 | {{-- --}} 66 | 67 | 68 | 69 | @endforeach 70 | 71 |
uriactionnamemiddlewarehost
@include('klaravel::ui.badge',['type' => $action_color, 'title'=> $action_value]) 37 | 38 | {{ $route['uri'] }} 39 | 40 | {{ isset($action) ? last(explode('\\', $action)) : '' }}{{ $route_name }} 44 | @php 45 | $middles = explode(',', $middleware); 46 | @endphp 47 | @foreach ($middles as $sMiddle) 48 | @if (str_contains($sMiddle,':')) 49 | @php 50 | $accumulated = $sMiddle; 51 | @endphp 52 | @continue 53 | @endif 54 | @php 55 | if (isset($accumulated)) { 56 | $sMiddle=$accumulated.','.$sMiddle; 57 | unset($accumulated); 58 | } 59 | @endphp 60 | {!! $loop->index >1 && str_contains($sMiddle,'\\') ? '
' : '' !!} 61 | @include('klaravel::ui.badge',['type' => 'dark', 'title'=> $sMiddle ]) 62 | 63 | @endforeach 64 |
{{ isset($middleware) ? last(explode('\\', $middleware)) : '-' }}{{ $route['host'] }}
72 | @else 73 | @includeif('klaravel::_parts.no-records', ['recrods_name' => 'backups']) 74 | @endif 75 | -------------------------------------------------------------------------------- /resources/admin/routes.blade.php: -------------------------------------------------------------------------------- 1 | @php 2 | $title = 'Route listing (kLaravel)'; 3 | @endphp 4 | 5 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 6 | 7 | @section('content') 8 |
9 | @card(['title' => 'List routes', 'reload_btn' => true]) 10 | @include('klaravel::ui.tables.actions-menu', [ 11 | 'model_name' => 'kLara.routes', 12 | 'hide_add_menu' => true, 13 | 'hide_per_page' => true, 14 | ]) 15 | 16 | @if (count($routes)>0) 17 |
18 | Found {{count($routes)}} routes. 19 |
20 | @endif 21 | 22 |
23 | @includeIf('klaravel::admin.routes-table') 24 |
25 | @endcard 26 |
27 | @endsection 28 | -------------------------------------------------------------------------------- /resources/admin/sessions.blade.php: -------------------------------------------------------------------------------- 1 | @php 2 | $title = 'Activity sessions (kLaravel)'; 3 | @endphp 4 | 5 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 6 | 7 | @section('content') 8 |
9 | @card(['title' => 'Latest site visitors', 'reload_btn' => true]) 10 | 11 | @component('klaravel::ui.tables.actions-menu', [ 12 | 'model_name' => 'kSessions', 13 | 'hide_add_menu' => true, 14 | 'hide_search' => true, 15 | ]) 16 | 21 | @php 22 | $tLimit = session(SESSION_TIME_LIMIT_CACHE); 23 | @endphp 24 | @component('klaravel::ui.dropdown', [ 25 | 'title' => ' '. ($tLimit ?: 'No time limit'), 26 | 'class' => ' mr-3', 27 | 'active' => $tLimit != '', 28 | ]) 29 | 30 | @foreach (['5-m','15-m','30-m','1-h', '3-h','8-h','12-h','24-h'] as $curTime) 31 | @php 32 | $selected = $tLimit == $curTime ? ' active': ''; 33 | $carst = explode('-',$curTime); 34 | @endphp 35 | 36 | {{$carst[0] . $carst[1]}} 37 | 38 | @endforeach 39 | 40 | @endcomponent 41 | 42 | 43 | @endcomponent 44 | 45 | 48 | 49 |
50 | @includeIf('klaravel::admin.sessions-table') 51 |
52 | @endcard 53 |
54 | @endsection 55 | -------------------------------------------------------------------------------- /resources/assets/js/components/ElementDate.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 30 | -------------------------------------------------------------------------------- /resources/assets/js/components/ElementRange.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 37 | -------------------------------------------------------------------------------- /resources/assets/js/components/ElementSelect.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 70 | -------------------------------------------------------------------------------- /resources/assets/js/components/ElementUpload.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 71 | 72 | 77 | -------------------------------------------------------------------------------- /resources/assets/js/klaravel.js: -------------------------------------------------------------------------------- 1 | /* 2 | // file initialization example. 3 | import ElementUI from 'element-ui'; 4 | import locale from 'element-ui/lib/locale/lang/es'; 5 | Vue.use(ElementUI, { locale }); 6 | 7 | require('klaravel'); <----------This file. 8 | import '~/../sass/element_variables.scss'; 9 | 10 | // Webpack configuration to read the library. 11 | .webpackConfig({ 12 | resolve: { 13 | symlinks: false, 14 | modules: [ 15 | path.resolve(__dirname, 'vendor/ksoft/klaravel/resources/assets/js'), 16 | 'node_modules' 17 | ], 18 | alias: { 19 | 'vue$': 'vue/dist/vue.js', 20 | '~': path.join(__dirname, './resources/assets/js'), 21 | '@': path.join(__dirname, './resources/assets/js/components') 22 | } 23 | } 24 | }) 25 | 26 | */ 27 | 28 | Vue.component( 29 | 'klaravel-element-range', 30 | require('./components/ElementRange.vue') 31 | ); 32 | Vue.component( 33 | 'klaravel-element-upload', 34 | require('./components/ElementUpload.vue') 35 | ); 36 | Vue.component( 37 | 'klaravel-element-select', 38 | require('./components/ElementSelect.vue') 39 | ); 40 | -------------------------------------------------------------------------------- /resources/assets/sass/bootstrap.css: -------------------------------------------------------------------------------- 1 | .markdown-wrapper { margin-bottom: 4rem; } 2 | .markdown-wrapper h1 { margin-bottom: 1.5rem; } 3 | .markdown-wrapper h4, .markdown-wrapper h5 { font-size: 1.4rem; margin-top: 3rem; margin-bottom: 1.5rem; } 4 | .markdown-wrapper h4 { text-transform: uppercase; } 5 | 6 | .album .stars { color: #bf021b; font-size: 0.8rem; display: inline-block; } 7 | 8 | footer { color: #6f6d70; font-size: 0.9em; } 9 | footer a { color: #6f6d70; } 10 | footer .footer__version { float: left; text-align: left; } 11 | footer .footer__credits { float: right; text-align: center; } 12 | footer .footer__brand { width: 2.3em; margin-right: 12px; height: auto; vertical-align: middle; } 13 | 14 | @media (max-width: 640px) { .footer__version { float: none; } 15 | .footer__credits { float: none; } } 16 | .pulse { color: #bf021b; animation-name: pulse_animation; animation-duration: 4000ms; transform-origin: 50% 100%; animation-iteration-count: infinite; animation-timing-function: linear; } 17 | 18 | @keyframes pulse_animation { 0% { transform: scale(1); } 19 | 35% { transform: scale(1); } 20 | 40% { transform: scale(1.2); } 21 | 45% { transform: scale(1); } 22 | 55% { transform: scale(1); } 23 | 60% { transform: scale(1.3); } 24 | 65% { transform: scale(1); } 25 | 100% { transform: scale(1); } } 26 | .table .excerpt { font-size: 0.9rem; } 27 | .table .btn-width { width: 32px; text-align: center; } 28 | .table .btn-actions { width: 80px; text-align: center; } 29 | 30 | .badge-counter { min-width: 52px; } 31 | 32 | .klara-content .card-header { color: #fff; background: #4b545c; text-transform: uppercase; font-weight: 600; } 33 | .klara-content h3 { margin-top: 1rem; margin-bottom: 1.5rem; } 34 | .klara-content .nav-item:has(.nav-link.active) { background: #cc9988 !important; } 35 | .klara-content .nav-item:has(.nav-link.active)::after { display: block; float: left; margin-right: -0.25em; margin-left: -0.25em; padding: 0 0.5em; color: #e14a0c; font-family: 'Font Awesome 5 Free'; color: black; content: '\f0da'; } 36 | .klara-content .nav-link { border-left: 5px solid #fff; } 37 | .klara-content .nav-link.active { background: #fff; border-left: 5px solid #cc0000; } 38 | .klara-content .nav-link:hover { background: #fff; } 39 | 40 | nav.navbar { display: block; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04); background: #fff; transition: all 0.3s ease-out; } 41 | 42 | p { color: #666; } 43 | 44 | .vue-notifyjs .alert { z-index: 1030; } 45 | 46 | .thead-dark th, .thead-dark td { text-transform: uppercase; font-weight: normal; } 47 | 48 | .nav-tabs.formtab { border-bottom: none; } 49 | 50 | .nav-tabs.formtab .nav-link.active { background-color: #fff; } 51 | 52 | .icon-logo { margin-right: 6px; } 53 | 54 | :root { --jumbotron-padding-y: 3rem; } 55 | 56 | body { background-color: #fff; } 57 | 58 | .jumbotron { padding-top: var(--jumbotron-padding-y); padding-bottom: var(--jumbotron-padding-y); margin-bottom: 0; background-color: #fff; } 59 | .jumbotron p:last-child { margin-bottom: 0; } 60 | 61 | @media (min-width: 768px) { .jumbotron { padding-top: calc(var(--jumbotron-padding-y) * 2); padding-bottom: calc(var(--jumbotron-padding-y) * 2); } } 62 | .jumbotron-heading { font-weight: 300; } 63 | 64 | .jumbotron .container { max-width: 40rem; } 65 | 66 | .section { padding-top: 3.2rem; padding-bottom: 4.2rem; } 67 | 68 | .box-shadow { box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.05); } 69 | 70 | ul.top-right-menu li.nav-item.dropdown { margin-left: 8px; } 71 | ul.top-right-menu li.nav-item.dropdown i { font-size: 1.2rem; margin-right: 4px; } 72 | 73 | ul.top-left-menu li.nav-item { margin-right: 4px; } 74 | 75 | /*# sourceMappingURL=bootstrap.css.map */ 76 | -------------------------------------------------------------------------------- /resources/assets/sass/bootstrap.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,iBAAkB,GAChB,aAAa,EAAE,IAAI;AACnB,oBAAG,GACD,aAAa,EAAE,MAAM;AAEvB,0CAAO,GACL,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,IAAI,EAChB,aAAa,EAAE,MAAM;AAEvB,oBAAG,GACD,cAAc,EAAE,SAAS;;ACV3B,aAAO,GACL,KAAK,ECFF,OAAO,EDGV,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY;;AEJzB,MAAO,GACL,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,KAAK;AAChB,QAAE,GACA,KAAK,EAAE,OAAO;AAEhB,uBAAiB,GACf,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,IAAI;AAElB,uBAAiB,GACf,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,MAAM;AAEpB,qBAAe,GACb,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,IAAI,EAClB,MAAM,EAAE,IAAI,EACZ,cAAc,EAAE,MAAM;;AAI1B,yBAA0B,GACxB,gBAAiB,GACf,KAAK,EAAE,IAAI;EAEb,gBAAiB,GACf,KAAK,EAAE,IAAI;AC3Bf,MAAO,GACL,KAAK,EFDA,OAAO,EEEZ,cAAc,EAAE,eAAe,EAC/B,kBAAkB,EAAE,MAAM,EAC1B,gBAAgB,EAAE,QAAQ,EAC1B,yBAAyB,EAAE,QAAQ,EACnC,yBAAyB,EAAE,MAAM;;AAGnC,0BAyBC,GAxBC,EAAG,GACD,SAAS,EAAE,QAAQ;EAErB,GAAI,GACF,SAAS,EAAE,QAAQ;EAErB,GAAI,GACF,SAAS,EAAE,UAAU;EAEvB,GAAI,GACF,SAAS,EAAE,QAAQ;EAErB,GAAI,GACF,SAAS,EAAE,QAAQ;EAErB,GAAI,GACF,SAAS,EAAE,UAAU;EAEvB,GAAI,GACF,SAAS,EAAE,QAAQ;EAErB,IAAK,GACH,SAAS,EAAE,QAAQ;AC/BrB,eAAS,GACP,SAAS,EAAE,MAAM;AAEnB,iBAAW,GACT,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,MAAM;AAEpB,mBAAa,GACX,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,MAAM;;AAItB,cAAe,GACb,SAAS,EAAE,IAAI;;ACdf,2BAAY,GACV,KAAK,EAAE,IAAI,EACX,UAAU,EAAE,OAAoB,EAChC,cAAc,EAAE,SAAS,EACzB,WAAW,EAAE,GAAG;AAElB,iBAAE,GACA,UAAU,EAAE,IAAI,EAChB,aAAa,EAAE,MAAM;AAEvB,8CAAgC,GAC9B,UAAU,EAAE,kBAAkB;AAC9B,qDAAS,GACP,OAAO,EAAE,KAAK,EACd,KAAK,EAAE,IAAI,EACX,YAAY,EAAE,OAAO,EACrB,WAAW,EAAE,OAAO,EACpB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EAEd,WAAW,EAAE,qBAAqB,EAClC,KAAK,EAAE,KAAc,EACrB,OAAO,EAAE,OAAO;AAGpB,wBAAU,GACR,WAAW,EAAE,cAAc;AAC3B,+BAAS,GACP,UAAU,EAAE,IAAI,EAChB,WAAW,EAAE,iBAAiB;AAGhC,8BAAQ,GACN,UAAU,EAAE,IAAI;;AJvBtB,UAAW,GACT,OAAO,EAAE,KAAK,EACd,UAAU,EAAE,6BAA6B,EACzC,UAAU,EAAE,IAAI,EAChB,UAAU,EAAE,iBAAiB;;AAK/B,CAAE,GACA,KAAK,EAAC,IAAI;;AAGZ,oBAAqB,GACnB,OAAO,EAAE,IAAI;;AAIf,8BACe,GACb,cAAc,EAAE,SAAS,EACzB,WAAW,EAAE,MAAM;;AAarB,iBAAkB,GAChB,aAAa,EAAE,IAAI;;AAErB,kCAAmC,GACjC,gBAAgB,EAAE,IAAI;;AAOxB,UAAW,GACT,YAAY,EAAE,GAAG;;AAGnB,KAAM,GACJ,qBAAqB,CAAC,KAAK;;AAG7B,IAAK,GAEH,gBAAgB,EAAE,IAAI;;AAGxB,UAAW,GACT,WAAW,EAAE,0BAA0B,EACvC,cAAc,EAAE,0BAA0B,EAC1C,aAAa,EAAE,CAAC,EAChB,gBAAgB,EAAE,IAAI;AACtB,uBAAa,GACX,aAAa,EAAE,CAAC;;AAIpB,yBAA0B,GACxB,UAAW,GACT,WAAW,EAAE,oCAAoC,EACjD,cAAc,EAAE,oCAAoC;AAIxD,kBAAmB,GACjB,WAAW,EAAE,GAAG;;AAGlB,qBAAsB,GACpB,SAAS,EAAE,KAAK;;AAGlB,QAAS,GACP,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM;;AAGxB,WAAY,GACV,UAAU,EAAE,qCAAqC;;AAIjD,sCAAqB,GACnB,WAAW,EAAE,GAAG;AAChB,wCAAE,GACA,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,GAAG;;AAKrB,4BAAY,GACV,YAAY,EAAE,GAAG", 4 | "sources": ["markdown.scss","stars.scss","bootstrap.scss","footer.scss","heart.scss","tables.scss","klara.scss"], 5 | "names": [], 6 | "file": "bootstrap.css" 7 | } -------------------------------------------------------------------------------- /resources/assets/sass/bootstrap.scss: -------------------------------------------------------------------------------- 1 | $rojo: #bf021b; 2 | // @import '../../../node_modules/bootstrap/scss/functions'; 3 | // @import '../../../node_modules/bootstrap/scss/variables'; 4 | // @import '../../../node_modules/bootstrap/scss/mixins'; 5 | @import './markdown'; 6 | @import './stars'; 7 | @import './footer'; 8 | @import './heart'; 9 | @import './tables'; 10 | @import './klara'; 11 | 12 | nav.navbar { 13 | display: block; 14 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04); 15 | background: #fff; 16 | transition: all 0.3s ease-out; 17 | // padding-top: 26px; 18 | // padding-bottom: 26px; 19 | } 20 | 21 | p { 22 | color:#666; 23 | } 24 | 25 | .vue-notifyjs .alert { 26 | z-index: 1030; 27 | } 28 | 29 | // #navbarHeader li a.nav-link, 30 | .thead-dark th, 31 | .thead-dark td { 32 | text-transform: uppercase; 33 | font-weight: normal; 34 | } 35 | 36 | .thead-dark th, 37 | .thead-dark td { 38 | // text-align: center; 39 | } 40 | 41 | // .container { 42 | // max-width: 1200px; 43 | // @include make-container(); 44 | // } 45 | 46 | .nav-tabs.formtab { 47 | border-bottom: none; 48 | } 49 | .nav-tabs.formtab .nav-link.active { 50 | background-color: #fff; 51 | } 52 | // #navbarHeader li a.nav-link { 53 | // font-size: 0.9em; 54 | // line-height: 1.6em; 55 | // } 56 | 57 | .icon-logo { 58 | margin-right: 6px; 59 | } 60 | 61 | :root { 62 | --jumbotron-padding-y: 3rem; 63 | } 64 | 65 | body { 66 | // line-height: 1.72rem; 67 | background-color: #fff; 68 | } 69 | 70 | .jumbotron { 71 | padding-top: var(--jumbotron-padding-y); 72 | padding-bottom: var(--jumbotron-padding-y); 73 | margin-bottom: 0; 74 | background-color: #fff; 75 | p:last-child { 76 | margin-bottom: 0; 77 | } 78 | } 79 | 80 | @media (min-width: 768px) { 81 | .jumbotron { 82 | padding-top: calc(var(--jumbotron-padding-y) * 2); 83 | padding-bottom: calc(var(--jumbotron-padding-y) * 2); 84 | } 85 | } 86 | 87 | .jumbotron-heading { 88 | font-weight: 300; 89 | } 90 | 91 | .jumbotron .container { 92 | max-width: 40rem; 93 | } 94 | 95 | .section { 96 | padding-top: 3.2rem; 97 | padding-bottom: 4.2rem; 98 | } 99 | 100 | .box-shadow { 101 | box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.05); 102 | } 103 | 104 | ul.top-right-menu { 105 | li.nav-item.dropdown { 106 | margin-left: 8px; 107 | i { 108 | font-size: 1.2rem; 109 | margin-right: 4px; 110 | } 111 | } 112 | } 113 | ul.top-left-menu { 114 | li.nav-item { 115 | margin-right: 4px; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /resources/assets/sass/bt4.scss: -------------------------------------------------------------------------------- 1 | // sass --style compressed resources/assets/sass/bt4.scss resources/assets/sass/bt4.css 2 | $enable-rounded: true; 3 | $enable-shadows: true; 4 | $enable-gradients: true; 5 | $enable-caret: false; 6 | // $font-family-sans-serif: "Raleway", sans-serif; 7 | // $font-size-base: 0.9rem; 8 | // $line-height-base: 1.6; 9 | @import "../../../node_modules/bootstrap/scss/bootstrap"; 10 | -------------------------------------------------------------------------------- /resources/assets/sass/footer.scss: -------------------------------------------------------------------------------- 1 | footer { 2 | color: #6f6d70; 3 | font-size: 0.9em; 4 | a { 5 | color: #6f6d70; 6 | } 7 | .footer__version { 8 | float: left; 9 | text-align: left; 10 | } 11 | .footer__credits { 12 | float: right; 13 | text-align: center; 14 | } 15 | .footer__brand { 16 | width: 2.3em; 17 | margin-right: 12px; 18 | height: auto; 19 | vertical-align: middle; 20 | } 21 | } 22 | 23 | @media (max-width: 640px) { 24 | .footer__version { 25 | float: none; 26 | } 27 | .footer__credits { 28 | float: none; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /resources/assets/sass/heart.scss: -------------------------------------------------------------------------------- 1 | .pulse { 2 | color: $rojo; 3 | animation-name: pulse_animation; 4 | animation-duration: 4000ms; 5 | transform-origin: 50% 100%; 6 | animation-iteration-count: infinite; 7 | animation-timing-function: linear; 8 | } 9 | 10 | @keyframes pulse_animation { 11 | 0% { 12 | transform: scale(1); 13 | } 14 | 35% { 15 | transform: scale(1); 16 | } 17 | 40% { 18 | transform: scale(1.2); 19 | } 20 | 45% { 21 | transform: scale(1); 22 | } 23 | 55% { 24 | transform: scale(1); 25 | } 26 | 60% { 27 | transform: scale(1.3); 28 | } 29 | 65% { 30 | transform: scale(1); 31 | } 32 | 100% { 33 | transform: scale(1); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/assets/sass/klara.scss: -------------------------------------------------------------------------------- 1 | .klara-content { 2 | .card-header{ 3 | color: #fff; 4 | background: lighten(#343a40, 10); 5 | text-transform: uppercase; 6 | font-weight: 600; 7 | } 8 | h3{ 9 | margin-top: 1rem; 10 | margin-bottom: 1.5rem; 11 | } 12 | .nav-item:has(.nav-link.active) { 13 | background: #cc9988 !important; 14 | &::after { 15 | display: block; 16 | float: left; 17 | margin-right: -0.25em; 18 | margin-left: -0.25em; 19 | padding: 0 0.5em; 20 | color: #e14a0c; 21 | // margin-right: 0.25em; 22 | font-family: 'Font Awesome 5 Free'; 23 | color: rgba(#000, 80); 24 | content: '\f0da'; 25 | } 26 | } 27 | .nav-link { 28 | border-left: 5px solid #fff; 29 | &.active { 30 | background: #fff; 31 | border-left: 5px solid #cc0000; 32 | } 33 | 34 | &:hover { 35 | background: #fff; 36 | // border-left: 5px solid #cc0000; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /resources/assets/sass/markdown.scss: -------------------------------------------------------------------------------- 1 | .markdown-wrapper { 2 | margin-bottom: 4rem; 3 | h1 { 4 | margin-bottom: 1.5rem; 5 | } 6 | h4, h5 { 7 | font-size: 1.4rem; 8 | margin-top: 3rem; 9 | margin-bottom: 1.5rem; 10 | } 11 | h4 { 12 | text-transform: uppercase; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /resources/assets/sass/stars.scss: -------------------------------------------------------------------------------- 1 | .album { 2 | .stars { 3 | color: $rojo; 4 | font-size: 0.8rem; 5 | display: inline-block; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /resources/assets/sass/tables.scss: -------------------------------------------------------------------------------- 1 | .table { 2 | .excerpt { 3 | font-size: 0.9rem; 4 | } 5 | .btn-width { 6 | width: 32px; 7 | text-align: center; 8 | } 9 | .btn-actions { 10 | width: 80px; 11 | text-align: center; 12 | } 13 | } 14 | 15 | .badge-counter { 16 | min-width: 52px; 17 | } 18 | -------------------------------------------------------------------------------- /resources/crud/create.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 3 | 4 | @section('content') 5 |
6 | @foreach (config('ksoft.module.crud.includes', []) as $viewToInclude) 7 | @includeIf($viewToInclude) 8 | @endforeach 9 | @card(['title' => 'New ' . title_case($model_name)]) 10 | {!! Former::open_for_files()->route($model_name.'.store') !!} 11 | 12 | @includeIf($viewsBasePath.$model_name.'.form') 13 | {!! Former::close() !!} 14 | @endcard 15 |
16 | @endsection 17 | -------------------------------------------------------------------------------- /resources/crud/edit.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 3 | 4 | @section('content') 5 |
6 | @foreach (config('ksoft.module.crud.includes', []) as $viewToInclude) 7 | @includeIf($viewToInclude) 8 | @endforeach 9 | @card() 10 | {!! Former::open_for_files() 11 | ->route($model_name . '.update', $record ) 12 | ->populate( $record ) 13 | !!} 14 | 15 | @includeIf($viewsBasePath.$model_name.'.form', ['submitButtonText' => 'Update']) 16 | {!! Former::close() !!} 17 | @endcard 18 |
19 | @endsection 20 | -------------------------------------------------------------------------------- /resources/crud/index.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 3 | 4 | @section('content') 5 |
6 | @foreach (config('ksoft.module.crud.includes', []) as $viewToInclude) 7 | @includeIf($viewToInclude) 8 | @endforeach 9 | @card(['title' => 'Listing ' . title_case(str_plural($model_name))]) 10 | @includeIf('klaravel::ui.tables.actions-menu') 11 | @if ($records->total()>0) 12 | @includeIf('klaravel::ui.tables.pagination',['class'=> 'py-2 mt-2']) 13 |
14 | 15 | @includeIf($viewsBasePath.$model_name.'.table') 16 |
17 | @else 18 | @includeif('klaravel::_parts.no-records') 19 | @endif 20 | @endcard 21 |
22 | @endsection 23 | -------------------------------------------------------------------------------- /resources/layouts/app.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @includeIf('parts.hiddenCredits') 4 | 5 | 6 | 7 | 8 | 9 | 10 | Klaravel, by Sunnyface.com 11 | 12 | @include('klaravel::_kLara._parts._styles') 13 | @foreach (config('ksoft.module.crud.assets', []) as $useAssets) 14 | 15 | @endforeach 16 | @stack('stylesheets') 17 | 24 | 25 | 26 |
27 | @includeIf(config('ksoft.module.crud.header', 'klaravel::_parts.header')) 28 |
29 | @includeIf(config('ksoft.module.crud.errors', 'klaravel::ui.errors')) 30 | 31 | @yield('content') 32 |
33 | @includeIf(config('ksoft.module.crud.footer', 'klaravel::_parts.footer')) 34 | @stack('modals') 35 | 36 | 37 |
38 | 39 | 40 | 41 | 42 | @stack('scripts') 43 | @include('klaravel::_kLara._parts._scripts') 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /resources/layouts/crud.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @includeIf('parts.hiddenCredits') 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | @isset($model_name) 12 | {{ title_case(str_plural($model_name)) }} | 13 | @endisset 14 | {{ config('app.name', 'Klaravel, by Sunnyface.com') }} | Admin area 15 | 16 | 17 | @foreach (config('ksoft.module.crud.assets', []) as $useAssets) 18 | 19 | @endforeach 20 | @stack('stylesheets') 21 | 29 | 30 | 31 |
32 | @includeIf(config('ksoft.module.crud.header', 'klaravel::_parts.header')) 33 |
34 | @includeIf(config('ksoft.module.crud.errors', 'klaravel::ui.errors')) 35 | @yield('content') 36 |
37 | @includeIf(config('ksoft.module.crud.footer', 'klaravel::_parts.footer')) 38 | @stack('modals') 39 | 40 |
41 | 42 | @if (app()->isLocal()) 43 | 44 | @else 45 | 46 | 47 | 48 | @endif 49 | @stack('scripts') 50 | @include('klaravel::_kLara._parts._scripts') 51 | 52 | 53 | -------------------------------------------------------------------------------- /resources/ui/alert.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /resources/ui/badge.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ $slot ?? '' }}{!! $title ?? '' !!} 4 | 5 | -------------------------------------------------------------------------------- /resources/ui/button-group.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
6 | {{ $slot ?? '' }} 7 |
8 | -------------------------------------------------------------------------------- /resources/ui/card-deck-media.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | @foreach ($medias as $mediaItem) 4 | @php 5 | list($width,$height) = get_img_sizes($mediaItem->getPath('thumb')); 6 | @endphp 7 |
8 | {{$mediaItem->name}} 9 |
10 | 11 |

12 | {{ diff_date_for_humans($mediaItem->created_at) }} 13 | 14 | w: {!! $width>2000 ? ''.number($width).'': number($width) !!}, 15 | h: {!! $height>2000 ? ''.number($height).'': number($height) !!} 16 | 17 |

18 | 19 | 20 |

21 | 22 | {{$mediaItem->human_readable_size}} 23 | 24 | 25 | {{$mediaItem->mime_type}} 26 | 27 |

28 |
29 | 43 | 44 | 45 |
46 | @endforeach 47 |
48 | -------------------------------------------------------------------------------- /resources/ui/card.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | @isset($title) 4 |
5 | @isset($reload_btn) 6 | 7 | 8 | 9 | @endisset 10 | {!! $title !!} 11 |
12 | @endisset 13 | @isset($tabs) 14 |
15 | 33 |
34 | @endisset 35 |
36 | {{ $slot ?? '' }} 37 |
38 |
39 | -------------------------------------------------------------------------------- /resources/ui/carousel.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 41 | -------------------------------------------------------------------------------- /resources/ui/dropdown.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | -------------------------------------------------------------------------------- /resources/ui/errors.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @includeIf('flash::message') 3 | @isset($errors) 4 | @if ($errors->any()) 5 |
6 | 18 |
19 | @endif 20 | @endisset 21 | @if (session()->has('flash_message')) 22 |
23 |
24 | {!! session()->get('flash_message') !!} 25 | 28 |
29 |
30 | @endif 31 | @if (session()->has('flash_error')) 32 |
33 |
34 | {!! session()->get('flash_error') !!} 35 | 38 |
39 |
40 | @endif 41 | -------------------------------------------------------------------------------- /resources/ui/figure.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | {{ $slot ?? '' }} 4 | 5 | @isset($caption) 6 |
{!! $caption !!}
7 | @endisset 8 |
9 | -------------------------------------------------------------------------------- /resources/ui/forms/buttons.blade.php: -------------------------------------------------------------------------------- 1 | 2 | {!! Former::actions( 3 | Former::lg_primary_submit(isset($submitButtonText) ? $submitButtonText : 'Create new') ) 4 | ->class('text-center py-3 mt-4') !!} 5 | -------------------------------------------------------------------------------- /resources/ui/forms/radios.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | @foreach ($items as $itemKey => $itemLabel) 6 | 7 |
8 | 13 | 14 |
15 | @endforeach 16 |
17 |
18 | -------------------------------------------------------------------------------- /resources/ui/forms/textarea.blade.php: -------------------------------------------------------------------------------- 1 | 2 | {!! Former::textarea($name)->label($label)->rows(isset($rows) ? $rows : 4) !!} 3 | -------------------------------------------------------------------------------- /resources/ui/list-group.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 11 | -------------------------------------------------------------------------------- /resources/ui/map/script.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | -------------------------------------------------------------------------------- /resources/ui/menu-nav.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /resources/ui/modal.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | -------------------------------------------------------------------------------- /resources/ui/nav.blade.php: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /resources/ui/tab.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 20 |
21 | {{ $slot ?? '' }} 22 |
23 | -------------------------------------------------------------------------------- /resources/ui/tables/actions-menu.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 53 | -------------------------------------------------------------------------------- /resources/ui/tables/actions.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | {{-- @php 6 | $editBtnLink = !isset($hide_edit) || (isset($hide_edit) && !$hide_edit) 7 | ? route_has($model_name.'.edit', $item->id) 8 | : '#disabled" disabled="disabled'; 9 | @endphp 10 | 11 | 12 | --}} 13 | @if (!isset($hide_edit) || (isset($hide_edit) && !$hide_edit)) 14 | 15 | 16 | 17 | @endif 18 | 19 | {{$slot ?? ''}} 20 | 21 | @if (isset($item->sortable) && count($item->sortable)>0) 22 | @if (!isset($hide_sort)) 23 | @include('klaravel::ui.tables.sort-dropdown') 24 | @endif 25 | @endif 26 | 27 | @if (!isset($hide_delete) || (isset($hide_delete) && !$hide_delete)) 28 | @include('klaravel::ui.tables.btn-delete') 29 | @endif 30 | 31 | 32 |
33 | 34 | -------------------------------------------------------------------------------- /resources/ui/tables/booble.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /resources/ui/tables/btn-delete.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @php 3 | $deleteBtnEnabled = !isset($hide_delete) || (isset($hide_delete) && $hide_delete == false); 4 | $deleteBtnLink = $deleteBtnEnabled ? route_has($model_name.'.index') : '#disabled'; 5 | $confirmMsg = "event.preventDefault(); if (confirm('Confirm delete?')){ document.getElementById('delete-item-{$item->id}').submit();}"; 6 | @endphp 7 | 9 | 10 | 11 | 12 | @if ($deleteBtnEnabled) 13 | 17 | @endif 18 | -------------------------------------------------------------------------------- /resources/ui/tables/count-query.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @php 3 | $totalRecordCount = count($records); 4 | @endphp 5 | @if ($totalRecordCount>0) 6 |
7 | {!!$totalRecordCount !!} record{!! $totalRecordCount > 1 ? 's' : '' !!} total 8 |
9 | @else 10 |
11 |

No records found

12 |
13 | @endif 14 | -------------------------------------------------------------------------------- /resources/ui/tables/count.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @if ($records->total()>0) 3 |
4 | Showing records from {!! $records->firstItem() !!} to {!! $records->lastItem() !!} of {!! $records->total() !!} record{!! $records->total() > 1 ? 's' : '' !!} 5 |
6 | @else 7 |
8 |

No records found

9 |
10 | @endif 11 | -------------------------------------------------------------------------------- /resources/ui/tables/media_info.blade.php: -------------------------------------------------------------------------------- 1 | 2 | @if (isset($item)) 3 | {{$item->name}}
4 |
5 | {{$item->human_readable_size}} 6 |
7 |
{{$item->mime_type}}
8 | @else 9 | no $item defined 10 | @endif 11 | -------------------------------------------------------------------------------- /resources/ui/tables/order.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 6 | 7 | 8 |
9 |
10 | 12 | 13 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /resources/ui/tables/pagination.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /resources/ui/tables/sort-dropdown.blade.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 6 | 20 |
21 | -------------------------------------------------------------------------------- /resources/ui/tables/truncate.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | {!! $item_data ?? '' !!} 5 |
6 | 7 | -------------------------------------------------------------------------------- /src/Console/Commands/InstallPlugin.php: -------------------------------------------------------------------------------- 1 | argument('name'); 17 | $script_name = array_get(InstPlugins::$plugins, $plugin_name); 18 | if ($this->laravel->runningInConsole()) { 19 | $script = KLARAVEL_PATH .'/src/Console/plugins/composer_install.sh '.$script_name['composer']; 20 | $this->info(shell_exec('sh '.$script)); 21 | } else { 22 | $script = KLARAVEL_PATH ."/src/Console/plugins/composer_install.sh spatie/laravel-medialibrary:^6.0.0"; 23 | $res = exec("cd .. && sh ${script}"); 24 | 25 | // $command = 'cd .. && composer require spatie/laravel-medialibrary:^6.0.0'; 26 | // $command = 'cd .. && pwd && composer require ' . $script_name['composer'] .' --no-scripts'; 27 | // $res = exec($command); 28 | // $this->info(exec($composer_path . ' dump-autoload')); 29 | // logi($command); 30 | logi($res); 31 | return $res; 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Console/Commands/PublishConfig.php: -------------------------------------------------------------------------------- 1 | info('Publish config files'); 36 | 37 | if ($this->option('base-krud') || $this->option('base-ctrl') || $this->option('config') || $this->option('settings')) { 38 | $this->withoutUserInteraction(); 39 | } else { 40 | $this->withUserInteraction(); 41 | } 42 | } 43 | 44 | protected function withUserInteraction() 45 | { 46 | $optionSelected = $this->choice('What whould you like to publish?', ['all', 'Configuration', 'BaseKrudController'], 0); 47 | 48 | if ($optionSelected == 'all' || $optionSelected == 'Configuration') { 49 | $this->publishConfig(); 50 | $this->info('Publish configuration file: '); 51 | } 52 | 53 | if ($optionSelected == 'all' || $optionSelected == 'BaseKrudController') { 54 | $this->publishBaseKrud(); 55 | $this->info('Publish BaseKrudController file: '); 56 | } 57 | } 58 | 59 | protected function withoutUserInteraction() 60 | { 61 | if ($this->option('settings')) { 62 | $this->publishSettings(); 63 | $this->info('Publish configuration file: '); 64 | } 65 | 66 | if ($this->option('config')) { 67 | $this->publishConfig(); 68 | $this->info('Publish configuration file: '); 69 | } 70 | 71 | if ($this->option('base-krud')) { 72 | $this->publishBaseKrud('BaseKrudController'); 73 | $this->info('Publish BaseKrudController file: '); 74 | } 75 | if ($this->option('base-ctrl')) { 76 | $this->publishBaseKrud(); 77 | $this->info('Publish BaseCtrl file: '); 78 | } 79 | } 80 | 81 | protected function publishConfig(){ 82 | (new Publisher($this))->publishFile( 83 | KLARAVEL_PATH.'/stubs/config/ksoft.php', 84 | base_path('config'), 85 | 'ksoft.php' 86 | ); 87 | } 88 | 89 | protected function publishSettings(){ 90 | (new Publisher($this))->publishDirectory( 91 | KLARAVEL_PATH.'/stubs/config/settings', 92 | base_path('config/klara') 93 | ); 94 | } 95 | 96 | protected function publishBaseKrud($file='BaseCtrl'){ 97 | (new Publisher($this))->publishFile( 98 | KLARAVEL_PATH.'/stubs/Controllers/'.$file.'.php', 99 | base_path('app/Http/Controllers'), 100 | $file.'.php' 101 | ); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Console/Helpers/GeneratorFieldRelation.php: -------------------------------------------------------------------------------- 1 | type = array_shift($inputs); 17 | $relation->inputs = $inputs; 18 | 19 | return $relation; 20 | } 21 | 22 | public function getRelationFunctionText() 23 | { 24 | $modelName = $this->inputs[0]; 25 | switch ($this->type) { 26 | case '1t1': 27 | $functionName = camel_case($modelName); 28 | $relation = 'hasOne'; 29 | $relationClass = 'HasOne'; 30 | break; 31 | case '1tm': 32 | $functionName = camel_case(str_plural($modelName)); 33 | $relation = 'hasMany'; 34 | $relationClass = 'HasMany'; 35 | break; 36 | case 'mt1': 37 | $functionName = camel_case($modelName); 38 | $relation = 'belongsTo'; 39 | $relationClass = 'BelongsTo'; 40 | break; 41 | case 'mtm': 42 | $functionName = camel_case(str_plural($modelName)); 43 | $relation = 'belongsToMany'; 44 | $relationClass = 'BelongsToMany'; 45 | break; 46 | case 'hmt': 47 | $functionName = camel_case(str_plural($modelName)); 48 | $relation = 'hasManyThrough'; 49 | $relationClass = 'HasManyThrough'; 50 | break; 51 | default: 52 | $functionName = ''; 53 | $relation = ''; 54 | $relationClass = ''; 55 | break; 56 | } 57 | 58 | if (!empty($functionName) and !empty($relation)) { 59 | return $this->generateRelation($functionName, $relation, $relationClass); 60 | } 61 | 62 | return ''; 63 | } 64 | 65 | private function generateRelation($functionName, $relation, $relationClass) 66 | { 67 | $inputs = $this->inputs; 68 | $modelName = array_shift($inputs); 69 | 70 | $template = get_template('model.relationship', 'laravel-generator'); 71 | 72 | $template = str_replace('$RELATIONSHIP_CLASS$', $relationClass, $template); 73 | $template = str_replace('$FUNCTION_NAME$', $functionName, $template); 74 | $template = str_replace('$RELATION$', $relation, $template); 75 | $template = str_replace('$RELATION_MODEL_NAME$', $modelName, $template); 76 | 77 | if (count($inputs) > 0) { 78 | $inputFields = implode("', '", $inputs); 79 | $inputFields = ", '".$inputFields."'"; 80 | } else { 81 | $inputFields = ''; 82 | } 83 | 84 | $template = str_replace('$INPUT_FIELDS$', $inputFields, $template); 85 | 86 | return $template; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Console/Helpers/Publisher.php: -------------------------------------------------------------------------------- 1 | command = $command; 14 | } 15 | 16 | public function publishFile($source, $destinationPath, $fileName) 17 | { 18 | if (! is_dir($destinationPath)) { 19 | if (! mkdir($destinationPath, 0755, true)) { 20 | $this->command->error('Cant crate directory: '.$destinationPath); 21 | } 22 | } 23 | 24 | if (! is_writable($destinationPath)) { 25 | if (! chmod($destinationPath, 0755)) { 26 | $this->command->error('Destination path is not writable'); 27 | } 28 | } 29 | 30 | if (file_exists($source)) { 31 | if (! copy($source, $destinationPath.'/'.$fileName)) { 32 | $this->command->error('File was not copied'); 33 | } 34 | } else { 35 | $this->command->error('Source file does not exists'); 36 | } 37 | } 38 | 39 | public function publishDirectory($source, $destination) 40 | { 41 | if (! is_dir($source)) { 42 | $this->command->error('Bad source path'); 43 | } else { 44 | $dir = opendir($source); 45 | 46 | if (! is_dir($destination)) { 47 | if (! mkdir($destination, 0755, true)) { 48 | $this->command->error('Cant crate directory: '.$destination); 49 | } 50 | } 51 | 52 | while (false !== ($file = readdir($dir))) { 53 | if (($file != '.') && ($file != '..')) { 54 | if (is_dir($source.'/'.$file)) { 55 | $this->publishDirectory($source.'/'.$file, $destination.'/'.$file); 56 | } else { 57 | copy($source.'/'.$file, $destination.'/'.$file); 58 | } 59 | } 60 | } 61 | closedir($dir); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Console/plugins/composer_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | PLUGIN="$1" 5 | whoami 6 | # dir=$(cd ../ && pwd -P) 7 | composer require $($1) \ 8 | --sort-packages \ 9 | --no-scripts 10 | # php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="migrations" 11 | # # php artisan migrate 12 | # php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="config" 13 | # echo "For Controllers" 14 | # echo "##### CanUploadMedia TRAIT ######" 15 | # echo "Ksoft\Klaravel\Traits\CanUploadMedia" 16 | # echo "For Models" 17 | # echo "##### HasMediaTrait TRAIT ######" 18 | # echo "Spatie\MediaLibrary\HasMedia\HasMediaTrait" 19 | # echo "##### HasMedia INTERFACE ######" 20 | # echo "Spatie\MediaLibrary\HasMedia\Interfaces\HasMedia" 21 | # echo "For how to use see https://docs.spatie.be/laravel-medialibrary/v6/introduction" 22 | echo "hehee composer require $($1) as> " + $(whoami) 23 | -------------------------------------------------------------------------------- /src/Console/plugins/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( pwd )" 3 | PACKAGE="$1" 4 | composer require $PACKAGE --no-interaction --verbose 5 | echo "composer require $PACKAGE" 6 | echo $DIR 7 | -------------------------------------------------------------------------------- /src/Contracts/EloquentRepoContract.php: -------------------------------------------------------------------------------- 1 | limit > 0 46 | * 47 | * @param Illuminate\Support\Collection $records 48 | * @param integer $per_page Manually set pagination option. 49 | * @return Illuminate\Support\Collection 50 | * @return Illuminate\Pagination\LengthAwarePaginator 51 | */ 52 | public function paginateIf($records, $per_page = 0); 53 | 54 | /** 55 | * @param array $properties 56 | * @return Model 57 | */ 58 | public function create(array $properties); 59 | 60 | /** 61 | * Updates a record. 62 | * 63 | * @param $id 64 | * @param array $properties 65 | * @return Model 66 | */ 67 | public function update($id, array $properties); 68 | 69 | /** 70 | * Delete record of provided id. 71 | * 72 | * @param $id 73 | */ 74 | public function delete($id); 75 | } 76 | -------------------------------------------------------------------------------- /src/Facade.php: -------------------------------------------------------------------------------- 1 | Create activity logs table'; 18 | return back()->with('flash_error', 'Sorry, activity_log table does not exists.' .$installBtn); 19 | } 20 | $logItems = $this->getPaginatedActivityLogItems($request); 21 | $logsTags = Activity::distinct()->select('log_name')->get()->pluck('log_name'); 22 | $logSubjects = Activity::distinct()->select('subject_type')->whereNotNull('subject_type')->get()->pluck('subject_type'); 23 | 24 | return view('klaravel::admin.activitylog', compact('logItems', 'logsTags', 'logSubjects')); 25 | } 26 | 27 | public function destroy(Activity $activity) 28 | { 29 | $activity->delete(); 30 | return back()->with('flash_message', 'Activity log delete succesfully'); 31 | } 32 | 33 | public function massDestroy(Request $request) 34 | { 35 | $res = ''; 36 | 37 | if ($request->filled('clean_all') && $request->get('clean_all') == 'yes') { 38 | $allRecords = Activity::where('id', '>', 0)->delete(); 39 | return back()->with('flash_message', 'Succesfully deleted ' . $allRecords . ' record/s.'); 40 | } 41 | 42 | if ($request->filled('del_tag') && $request->filled('del_subject')) { 43 | $query = Activity::where('log_name', $request->del_tag); 44 | if ($request->query_type == 'OR') { 45 | $tags = $query->orWhere('subject_type', $request->del_subject)->delete(); 46 | } else { 47 | $tags = $query->where('subject_type', $request->del_subject)->delete(); 48 | } 49 | $res .= ' Deleted ' . $tags . ' logs by matching query.'; 50 | } else { 51 | if ($request->filled('del_tag')) { 52 | $tags = Activity::where('log_name', $request->get('del_tag'))->delete(); 53 | $res .= ' Deleted ' . $tags . ' logs by TAG.'; 54 | } 55 | 56 | if ($request->filled('del_subject')) { 57 | $subjects = Activity::where('subject_type', $request->get('del_subject'))->delete(); 58 | $res .= ' Deleted ' . $subjects . ' logs by Subject...'; 59 | } 60 | } 61 | 62 | return back()->with('flash_message', 'Mass deletion succesfull.' . $res); 63 | } 64 | 65 | protected function getPaginatedActivityLogItems($request): Paginator 66 | { 67 | $query = Activity::with('causer')->orderBy('created_at', 'DESC'); 68 | 69 | if ($request->filled('tag')) { 70 | $query->inLog($request->tag); 71 | } 72 | 73 | if ($request->filled('subject')) { 74 | $query->where('subject_type', $request->subject); 75 | } 76 | 77 | if ($request->filled('q')) { 78 | $query->where('description', 'LIKE', '%' . $request->q . '%'); 79 | } 80 | 81 | return $query->paginate(session(config('ksoft.CONSTANTS.take', 'PER_PAGE'), 25)); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Http/Controllers/BackupController.php: -------------------------------------------------------------------------------- 1 | files(config('backup.backup.name')); 13 | $backups = []; 14 | // make an array of backup files, with their filesize and creation date 15 | foreach ($files as $k => $f) { 16 | // only take the zip files into account 17 | if (substr($f, -4) == '.zip' && $disk->exists($f)) { 18 | $backups[] = [ 19 | 'file_path' => $f, 20 | 'file_name' => str_replace(config('backup.backup.name') . '/', '', $f), 21 | 'file_size' => humanReadableSize($disk->size($f)), 22 | 'last_modified' => createFromTimestamp($disk->lastModified($f)), 23 | ]; 24 | } 25 | } 26 | // reverse the backups, so the newest one would be on top 27 | $backups = array_reverse($backups); 28 | $routeName = config('ksoft.module.backup.route_name', 'backup'); 29 | return view("klaravel::admin.backups")->with(compact('backups', 'routeName')); 30 | } 31 | 32 | public function create() 33 | { 34 | try { 35 | Artisan::call('backup:run', config('ksoft.module.backup.extra_arguments', ['--only-db' => 'true'])); 36 | return back()->with('flash_success', 'Backup created succesfully'); 37 | } catch (Exception $e) { 38 | return back()->with('flash_error', $e->getMessage()); 39 | } 40 | } 41 | 42 | public function dbBackup() 43 | { 44 | try { 45 | Artisan::call('backup:run', ['--only-db' => 'true']); 46 | return back()->with('flash_success', 'DB Backup created succesfully'); 47 | } catch (Exception $e) { 48 | return back()->with('flash_error', $e->getMessage()); 49 | } 50 | } 51 | 52 | /** 53 | * Downloads a backup zip file. 54 | * 55 | * TODO: make it work no matter the flysystem driver (S3 Bucket, etc). 56 | */ 57 | public function download($file_name) 58 | { 59 | $file = config('backup.backup.name') . '/' . $file_name; 60 | $disk = Storage::disk(config('backup.backup.destination.disks')[0]); 61 | if ($disk->exists($file)) { 62 | $fs = Storage::disk(config('backup.backup.destination.disks')[0])->getDriver(); 63 | $stream = $fs->readStream($file); 64 | return \Response::stream(function () use ($stream) { 65 | fpassthru($stream); 66 | }, 200, [ 67 | "Content-Type" => $fs->getMimetype($file), 68 | "Content-Length" => $fs->getSize($file), 69 | "Content-disposition" => "attachment; filename=\"" . basename($file) . "\"", 70 | ]); 71 | } else { 72 | abort(404, "The backup file doesn't exist."); 73 | } 74 | } 75 | /** 76 | * Deletes a backup file. 77 | */ 78 | public function delete($file_name) 79 | { 80 | $disk = Storage::disk(config('backup.backup.destination.disks')[0]); 81 | if ($disk->exists(config('backup.backup.name') . '/' . $file_name)) { 82 | $disk->delete(config('backup.backup.name') . '/' . $file_name); 83 | return back(); 84 | } else { 85 | abort(404, "The backup file doesn't exist."); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Http/Controllers/CacheController.php: -------------------------------------------------------------------------------- 1 | Create Cache table'; 15 | return back()->with('flash_error', 'Sorry, cache table does not exists.'.$installBtn); 16 | } 17 | 18 | $records = Cache::orderBy('expiration', 'DESC') 19 | ->paginate(session(config('ksoft.CONSTANTS.take', 'PER_PAGE'), 50)); 20 | 21 | return view('klaravel::admin.cache', compact('records')); 22 | } 23 | 24 | public function delete(Cache $cache) 25 | { 26 | $cache->delete(); 27 | 28 | return back()->with('flash_message', 'Caché value deleted.'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | $request->get('perPage')]); 14 | 15 | if ($request->filled('redirect')) { 16 | return redirect(url('/' . $request->redirect)); 17 | } 18 | 19 | return back(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Http/Controllers/PluginsController.php: -------------------------------------------------------------------------------- 1 | InstPlugins::$plugins]); 14 | } 15 | 16 | public function installPlugin($plugin_name) 17 | { 18 | $script_name = array_get(InstPlugins::$plugins, $plugin_name); 19 | if (!$script_name) { 20 | return back() 21 | ->with('flash_error', 'Unable to find plugin "' . $plugin_name . '" to install'); 22 | } 23 | 24 | $exitCode = Artisan::call('ksoft:plugin', ['name' => $plugin_name]); 25 | 26 | return redirect(route('ksoft.plugins.index'))->with( 27 | 'flash_message', 28 | $exitCode . implode("
", InstPlugins::$postInstall[$plugin_name]) 29 | ); 30 | } 31 | 32 | public function uninstallPlugin($plugin_name) 33 | { 34 | $script_name = array_get(InstPlugins::$plugins, $plugin_name); 35 | if (!$script_name) { 36 | return back() 37 | ->with('flash_error', 'Unable to find plugin "' . $plugin_name . '" to install'); 38 | } 39 | $deletePack = explode(':', $script_name['composer']); 40 | $exitCode = exec("cd ../ && composer remove {$deletePack[0]} --no-interaction"); 41 | return back()->with( 42 | 'flash_message', $exitCode . '::: composer remove "' . $deletePack[0] . '"' 43 | ); 44 | } 45 | } 46 | 47 | // 'Unable to find plugin "'.$plugin_name.'" to install' 48 | -------------------------------------------------------------------------------- /src/Http/Controllers/SessionController.php: -------------------------------------------------------------------------------- 1 | Create Sessions table'; 16 | return back()->with('flash_error', 'Sorry, sessions table does not exists.'.$installBtn); 17 | } 18 | 19 | $query = $this->filterDates($request); 20 | 21 | $sessions = $query->paginate(session(config('ksoft.CONSTANTS.take', 'PER_PAGE'), 50)); 22 | 23 | return view('klaravel::admin.sessions', compact('sessions')); 24 | } 25 | 26 | public function delete(Session $session) 27 | { 28 | $session->delete(); 29 | 30 | return back()->with('flash_message', 'Record deleted.'); 31 | } 32 | 33 | protected function filterDates($request) 34 | { 35 | $query = Session::orderBy('last_activity', 'DESC'); 36 | 37 | if ($request->filled('limit')) { 38 | if ($request->get('limit') == 'X') { 39 | session()->forget(SESSION_TIME_LIMIT_CACHE); 40 | } else { 41 | $tlimit = $request->get('limit'); 42 | session([SESSION_TIME_LIMIT_CACHE => $tlimit]); 43 | } 44 | } else { 45 | $tlimit = session(SESSION_TIME_LIMIT_CACHE); 46 | } 47 | 48 | if (!isset($tlimit) ?? is_null($tlimit)) { 49 | return $query; 50 | } 51 | 52 | $tLAr = explode('-', $tlimit); 53 | 54 | switch (array_get($tLAr, 1)) { 55 | case 'm': 56 | return $query->where('last_activity', '>', now()->subMinutes($tLAr[0])->timestamp); 57 | break; 58 | case 'h': 59 | return $query->where('last_activity', '>', now()->subHours($tLAr[0])->timestamp); 60 | break; 61 | default: 62 | return $query; 63 | break; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Larapp.php: -------------------------------------------------------------------------------- 1 | 28 | * @version $Revision: 1.3 $ 29 | * @access public 30 | * @see https://github.com/kikoseijo/klaravel/blob/master/src/Larapp.php 31 | */ 32 | class Larapp 33 | { 34 | use CallsInteractions, UserModelOptions; 35 | 36 | /** 37 | * The Klaravel version. 38 | * Make this yours.. by setting it up on bootstrap. 39 | * Larapp::$version = '1.2.3'; 40 | */ 41 | public static $version = '0.0.0'; 42 | 43 | /** 44 | * Get a new user model instance. 45 | * 46 | * @return \Illuminate\Contracts\Auth\Authenticatable 47 | */ 48 | public static function user() 49 | { 50 | return new static::$userModel; 51 | } 52 | 53 | /** 54 | * Returns true if app version its Lumen 55 | * 56 | * @return boolean 57 | */ 58 | public static function isLumen() 59 | { 60 | return str_contains(app()->version(), 'Lumen'); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Models/Cache.php: -------------------------------------------------------------------------------- 1 | 'string', 13 | 'value' => 'array', 14 | ]; 15 | 16 | protected $dates = [ 17 | 'expiration', 18 | ]; 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/Models/Session.php: -------------------------------------------------------------------------------- 1 | 'string', 15 | ]; 16 | 17 | public function visitor() 18 | { 19 | return $this->belongsTo(config('auth.providers.users.model', 'App\User'), 'user_id'); 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Routing/KrudPolicyController.php: -------------------------------------------------------------------------------- 1 | take ?? session($perPageKey, 10); 22 | $records = $this->repo->withPagination($perPage, $request); 23 | 24 | $res = array_merge($this->loadCrudStyles(), [ 25 | 'records' => $records, 26 | 'model_name' => $this->path, 27 | ]); 28 | 29 | return $this->returnCustomView($res); 30 | } 31 | 32 | public function create() 33 | { 34 | $this->authorize('create', $this->repo->model()); 35 | $res = array_merge($this->loadCrudStyles(), ['model_name' => $this->path]); 36 | 37 | return $this->returnCustomView($res, 'create'); 38 | } 39 | 40 | public function store(Request $request) 41 | { 42 | $this->authorize('create', $this->repo->model()); 43 | $record = $this->interaction($this->createInteraction, [$request->all()]); 44 | 45 | return redirect(route($this->path . '.index'))->with('flash_message', 'Record added succesfully'); 46 | } 47 | 48 | public function show($id) 49 | { 50 | return redirect(route($this->path . '.index')); 51 | } 52 | 53 | public function edit($id) 54 | { 55 | $record = $this->repo->find($id); 56 | $this->authorize('update', $record); 57 | $res = array_merge($this->loadCrudStyles(), [ 58 | 'record' => $record, 59 | 'model_name' => $this->path, 60 | ]); 61 | 62 | return $this->returnCustomView($res, 'edit'); 63 | } 64 | 65 | public function update(Request $request, $id) 66 | { 67 | $record = $this->repo->find($id); 68 | $this->authorize('update', $record); 69 | $updatedRecord = $this->interaction($this->updateInteraction, [$record->id, $request->all()]); 70 | 71 | return redirect(route($this->path . '.index'))->with('flash_message', 'Record updated succesfully'); 72 | } 73 | 74 | public function destroy($id) 75 | { 76 | $record = $this->repo->find($id); 77 | $this->authorize('delete', $record); 78 | $record->delete(); 79 | 80 | return redirect(route($this->path . '.index'))->with('flash_message', 'Record deleted succesfully'); 81 | } 82 | 83 | protected function loadCrudStyles() 84 | { 85 | $viewsBasePath = config('ksoft.module.crud.views_base_path', ''); 86 | $crudWrapperClass = config('ksoft.style.crud_container_wrapper', 'container -body-block pb-5'); 87 | 88 | return [ 89 | 'viewsBasePath' => $viewsBasePath, 90 | 'crudWrapperClass' => $crudWrapperClass, 91 | ]; 92 | } 93 | 94 | protected function returnCustomView($data, $key = 'index') 95 | { 96 | $view = $data['viewsBasePath'] . $data['model_name'] . '.' . $key; 97 | 98 | return view()->exists($view) 99 | ? view($view, $data) 100 | : view('klaravel::crud.' . $key, $data); 101 | 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/Traits/ActiveScope.php: -------------------------------------------------------------------------------- 1 | where($key, 1); 23 | } 24 | } else { 25 | $query->where($type, 1); 26 | } 27 | return $query; 28 | } 29 | 30 | public function scopeNotActive($query, $type = 'active') 31 | { 32 | if (is_array($type)) { 33 | foreach ($type as $key) { 34 | $query->where($key, 0); 35 | } 36 | }else { 37 | $query->where($type, 0); 38 | } 39 | return $query; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Traits/CallsInteractions.php: -------------------------------------------------------------------------------- 1 | validate(); 51 | 52 | return static::interact($interaction, $parameters); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/Traits/CanChangeStatuses.php: -------------------------------------------------------------------------------- 1 | repo->find($id); 12 | 13 | if (!$record) { 14 | return back()->with('flash_error', 'Could not find record.'); 15 | } 16 | 17 | $statusKey = array_get($this->changeableStatus, $key); 18 | 19 | if ($statusKey == 'bool') { 20 | $newStatus = $status || $status == 'true' || mb_strtolower($status) == 'on' ? 1 : 0; 21 | } elseif (is_array($statusKey)) { 22 | if (in_array($status, $statusKey)) { 23 | $newStatus = $status; 24 | } else { 25 | 26 | return back()->with('flash_error', 'Sorry you trying to change a key: '.$key.' for a non declared value'); 27 | } 28 | } else { 29 | 30 | return back()->with('flash_error', 'Sorry you trying to change a non declared key: '.$key); 31 | } 32 | 33 | $record->{$key} = $newStatus; 34 | $record->save(); 35 | 36 | return back()->with('flash_message','Status changed succesfully!'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Traits/CanSortRecords.php: -------------------------------------------------------------------------------- 1 | repo->find($id); 12 | switch ($action) { 13 | case 'up': 14 | $record->moveOrderUp(); 15 | break; 16 | case 'down': 17 | $record->moveOrderDown(); 18 | break; 19 | case 'first': 20 | $record->moveToStart(); 21 | break; 22 | case 'last': 23 | $record->moveToEnd(); 24 | break; 25 | } 26 | 27 | return back()->with('flash_message','Record moved succesfully'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Traits/CanUploadMedia.php: -------------------------------------------------------------------------------- 1 | name('MODEL_PATH.media.upload'); 12 | * Route::get('MODEL_PATH/{id}/remove-media/{media?}', 'MODELController@remove')->name('MODEL_PATH.media.remove'); 13 | * ---------------- 14 | * VUE 15 | * ---------------- 16 | * 21 | * 22 | * props: ['fotos', 'recordId', 'baseUrl', 'isMultiple'], 23 | */ 24 | trait CanUploadMedia 25 | { 26 | public function upload(Request $request, $id) 27 | { 28 | $record = $this->repo->find($id); 29 | $record->addMediaFromRequest('foto')->toMediaCollection('images'); 30 | 31 | return $record->getMedia(); 32 | } 33 | 34 | public function remove($id, Media $media) 35 | { 36 | $record = $this->repo->find($id); 37 | $record->deleteMedia($media); // Fix for deleting the media from storage also. 38 | 39 | return redirect(route($this->path.'.edit', $id).'#fotos')->with('flash_message', 'Media removed succesfully.'); 40 | } 41 | 42 | public function mediaDefault($id, Media $media) 43 | { 44 | // $record = $this->repo->find($id); 45 | // $medias = $record->media()->get()->puck('id'); 46 | 47 | $media->order_column = 1; 48 | $media->save(); 49 | 50 | 51 | return redirect(route($this->path.'.edit', $id).'#fotos')->with('flash_message', 'Media updated succesfully.'); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Traits/HasLogs.php: -------------------------------------------------------------------------------- 1 | morphMany( 19 | ActivitylogServiceProvider::determineActivityModel(), 20 | 'subject' 21 | )->orderBy('id', 'DESC'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Traits/JsonTrait.php: -------------------------------------------------------------------------------- 1 | response = new JsonResponse()); 25 | } 26 | 27 | public function json() { 28 | return (is_null($this->response))? $this->newJson(): $this->response; 29 | } 30 | 31 | public function hasErrors() { 32 | return $this->json()->hasErrors(); 33 | } 34 | 35 | public function isSuccess() { 36 | return $this->json()->isSuccess(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/Traits/KrudControllerTrait.php: -------------------------------------------------------------------------------- 1 | repo->withRelationships($request); 25 | } 26 | 27 | /** 28 | * @param Request $request 29 | * @return mixed 30 | */ 31 | public function search(Request $request) 32 | { 33 | $query = str_replace('*', '%', $request->input('q')); 34 | 35 | return $this->repo->findWhereLike('name', '%'.$query.'%', 10); 36 | } 37 | 38 | /** 39 | * Store a newly created record in storage. 40 | * POST /records 41 | * 42 | * @param Illuminate\Http\Request $request 43 | * 44 | * @return Response 45 | */ 46 | public function store(Request $request) 47 | { 48 | $record = $this->interaction($this->createInteraction, [$request->all()]); 49 | return $this->createdResponse($record); 50 | } 51 | 52 | /** 53 | * Update the specified record in storage. 54 | * PUT/PATCH /records/{id} 55 | * 56 | * @param int $id 57 | * @param Illuminate\Http\Request $request 58 | * 59 | * @return Response 60 | */ 61 | public function update(Request $request, $id) 62 | { 63 | $record = $this->interaction($this->updateInteraction, [$id, $request->all()]); 64 | return $this->successResponse($record); 65 | } 66 | 67 | /** 68 | * Remove the specified record from storage. 69 | * DELETE /records/{id} 70 | * 71 | * @param int $id 72 | * 73 | * @return Response 74 | */ 75 | public function destroy($id) 76 | { 77 | $this->repo->delete($id); 78 | return $this->deletedResponse(); 79 | } 80 | 81 | /** 82 | * Execute the given interaction. 83 | * 84 | * This performs the common validate and handle methods for common interactions. 85 | * 86 | * @param string $interaction 87 | * @param array $parameters 88 | * @return mixed 89 | */ 90 | protected function interaction($interaction, array $parameters) 91 | { 92 | $this->call($interaction.'@validator', $parameters)->validate(); 93 | 94 | return $this->call($interaction, $parameters); 95 | } 96 | 97 | /** 98 | * Will call interacion handle function if no other method its defined. 99 | * 100 | * @param string $interaction 101 | * @param array $parameters 102 | * @return mixed 103 | */ 104 | protected function call($interaction, array $parameters = []) 105 | { 106 | if (!str_contains($interaction, '@')) { 107 | $interaction = $interaction.'@handle'; 108 | } 109 | 110 | list($class, $method) = explode('@', $interaction); 111 | 112 | $base = class_basename($class); 113 | 114 | return call_user_func_array([app($class), $method], $parameters); 115 | } 116 | 117 | abstract protected function successResponse($data); 118 | abstract protected function createdResponse($data); 119 | abstract protected function deletedResponse(); 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/Traits/LumenResponsesTrait.php: -------------------------------------------------------------------------------- 1 | json( 16 | (new JsonResponse($data))->toArray(), 17 | 200 18 | ); 19 | } 20 | 21 | protected function createdResponse($data) 22 | { 23 | return response()->json( 24 | (new JsonResponse($data, 201))->toArray(), 25 | 201 26 | ); 27 | } 28 | 29 | protected function notFoundResponse() 30 | { 31 | return response()->json( 32 | (new JsonResponse('Resource Not Found', 201))->toArray(), 33 | 201 34 | ); 35 | } 36 | 37 | protected function deletedResponse() 38 | { 39 | return response()->json( 40 | (new JsonResponse('Resource deleted succesfully', 204))->toArray(), 41 | 204 42 | ); 43 | } 44 | 45 | protected function clientErrorResponse($data) 46 | { 47 | return response()->json( 48 | (new JsonResponse($data, 422))->toArray(), 49 | 422 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Traits/QueryFiltersTrait.php: -------------------------------------------------------------------------------- 1 | attrsFilter as $key) { 13 | if ($request->filled($key)) { 14 | $this->query->where($key, 'LIKE', '%'.$request->get($key).'%'); 15 | } 16 | } 17 | } 18 | 19 | protected function applyEqualTypeFilter($request, $itemsArray, $multiple = true) 20 | { 21 | foreach ($itemsArray as $key => $value) { 22 | if ($request->filled($value)) { 23 | if ($key != 0 && $multiple) { 24 | $this->query->orWhere($value, $request->get($value)); 25 | } else { 26 | $this->query->where($value, $request->get($value)); 27 | } 28 | } 29 | } 30 | } 31 | 32 | protected function removeSingleAttrFilter(array $filtro) 33 | { 34 | if (count($filtro)>0) { 35 | $this->attrsFilter = array_diff($this->attrsFilter, $filtro); 36 | } 37 | } 38 | 39 | protected function filterBool($attr, $value) 40 | { 41 | if ($value == 'NULL') { // hardcoded en VUE - could be any string. 42 | $this->query->whereNull($attr); 43 | } elseif ($value == 'NOT_NULL'){ 44 | $this->query->whereNotNull($attr); 45 | } else { 46 | $this->query->where($attr, $value); 47 | } 48 | } 49 | 50 | protected function applyDateRangeFilter($request, $field = 'dateRange', $attr = 'created_at') 51 | { 52 | if ($request->filled($field)) { 53 | 54 | $range = $request->get($field); 55 | 56 | if ($range[0] == $range[1]) { 57 | $this->query->whereDate($attr, $range[0]); 58 | } else if (count($range)>1) { 59 | $this->query->whereDate($attr, '>=', $range[0]) 60 | ->whereDate($attr, '<=', $range[1]); 61 | } 62 | } 63 | } 64 | 65 | // this is a range comming from VUE element-ui 66 | protected function applyDateSessionFilter($request, $attr = 'created_at') 67 | { 68 | $session_name_from = config('ksoft.module.crud.session_range_from'); 69 | $session_name_to = config('ksoft.module.crud.session_range_from'); 70 | 71 | if ($request->has('d')){ 72 | $desde = $request->get('d'); 73 | $hasta = $request->get('a'); 74 | 75 | session([$session_name_from => $desde]); 76 | session([$session_name_to => $hasta]); 77 | } else { 78 | $desde = session($session_name_from); 79 | $hasta = session($session_name_to); 80 | } 81 | 82 | if (!is_null($desde) && !is_null($hasta)) { 83 | 84 | session([$session_name_from => $desde]); 85 | session([$session_name_to => $hasta]); 86 | 87 | if ($desde == $hasta) { 88 | $this->query->whereDate($attr, $desde); 89 | } else if (!is_null($desde) && !is_null($hasta)) { 90 | $this->query->whereDate($attr, '>=', $desde) 91 | ->whereDate($attr, '<=', $hasta); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Traits/UserModelOptions.php: -------------------------------------------------------------------------------- 1 | call($interaction.'@validator', $parameters)->validate(); 22 | 23 | return $this->call($interaction, $parameters); 24 | } 25 | 26 | /** 27 | * Will call interacion handle function if no other method its defined. 28 | * 29 | * @param string $interaction 30 | * @param array $parameters 31 | * @return mixed 32 | */ 33 | protected function call($interaction, array $parameters = []) 34 | { 35 | if (!str_contains($interaction, '@')) { 36 | $interaction = $interaction.'@handle'; 37 | } 38 | 39 | list($class, $method) = explode('@', $interaction); 40 | 41 | $base = class_basename($class); 42 | 43 | return call_user_func_array([app($class), $method], $parameters); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Utils/InstPlugins.php: -------------------------------------------------------------------------------- 1 | [ 9 | 'name' => 'Spatie Media Library', 10 | 'composer' => 'spatie/laravel-medialibrary', 11 | 'main_class' => 'Spatie\MediaLibrary\MediaLibraryServiceProvider', 12 | 'script_name' => 'spatie_laravel_media_library', 13 | 'help_url' => 'https://docs.spatie.be/laravel-medialibrary/v6/introduction' 14 | ], 15 | ]; 16 | 17 | public static $postInstall = [ 18 | 'medialibrary' => [ 19 | "For Controllers", 20 | "##### CanUploadMedia TRAIT ######", 21 | "Ksoft\Klaravel\Traits\CanUploadMedia", 22 | "For Models", 23 | "##### HasMediaTrait TRAIT ######", 24 | "Spatie\MediaLibrary\HasMedia\HasMediaTrait", 25 | "##### HasMedia INTERFACE ######", 26 | "Spatie\MediaLibrary\HasMedia\Interfaces\HasMedia", 27 | ] 28 | ]; 29 | } 30 | -------------------------------------------------------------------------------- /stubs/Contracts/ExampleCreate.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 21 | $this->authorizeResource($repo->model(), $param); 22 | $this->path = $path; 23 | $this->repo = $repo; 24 | } 25 | 26 | public function index(Request $request) 27 | { 28 | $perPageKey = config('ksoft.CONSTANTS.take', 'PER_PAGE'); 29 | $perPage = $request->take ?? session($perPageKey, 10); 30 | $records = $this->repo->withPagination($perPage, $request); 31 | 32 | $res = array_merge($this->loadCrudStyles(), [ 33 | 'records' => $records, 34 | 'model_name' => $this->path, 35 | ]); 36 | 37 | return $this->returnCustomView($res); 38 | } 39 | 40 | public function create() 41 | { 42 | $res = array_merge($this->loadCrudStyles(), ['model_name' => $this->path]); 43 | 44 | return $this->returnCustomView($res, 'create'); 45 | } 46 | 47 | public function store(Request $request) 48 | { 49 | $record = $this->interaction($this->createInteraction, [$request->all()]); 50 | 51 | return redirect(route($this->path . '.index'))->with('flash_message', 'Record added succesfully'); 52 | } 53 | 54 | public function show($record) 55 | { 56 | return redirect(route($this->path . '.index')); 57 | } 58 | 59 | public function edit($record) 60 | { 61 | $res = array_merge($this->loadCrudStyles(), [ 62 | 'record' => $record, 63 | 'model_name' => $this->path, 64 | ]); 65 | 66 | return $this->returnCustomView($res, 'edit'); 67 | } 68 | 69 | public function update(Request $request, $record) 70 | { 71 | $updatedRecord = $this->interaction($this->updateInteraction, [$record->id, $request->all()]); 72 | 73 | return redirect(route($this->path . '.index'))->with('flash_message', 'Record updated succesfully'); 74 | } 75 | 76 | public function destroy($record) 77 | { 78 | $record->delete(); 79 | 80 | return redirect(route($this->path . '.index'))->with('flash_message', 'Record deleted succesfully'); 81 | } 82 | 83 | protected function loadCrudStyles() 84 | { 85 | $viewsBasePath = config('ksoft.module.crud.views_base_path', ''); 86 | $crudWrapperClass = config('ksoft.style.crud_container_wrapper', 'container -body-block pb-5'); 87 | 88 | $baseCrudStyles = [ 89 | 'viewsBasePath' => $viewsBasePath, 90 | 'crudWrapperClass' => $crudWrapperClass, 91 | ]; 92 | 93 | if (method_exists($this, 'getExtraData')) { 94 | return array_merge($baseCrudStyles, $this->getExtraData()); 95 | } 96 | 97 | return $baseCrudStyles; 98 | } 99 | 100 | protected function returnCustomView($data, $key = 'index') 101 | { 102 | $view = $data['viewsBasePath'] . $data['model_name'] . '.' . $key; 103 | 104 | return view()->exists($view) 105 | ? view($view, $data) 106 | : view('klaravel::crud.' . $key, $data); 107 | 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /stubs/Controllers/ExampleController.php: -------------------------------------------------------------------------------- 1 | createInteraction = %model%Create::class; 20 | $this->updateInteraction = %model%Update::class; 21 | 22 | parent::__construct('%model_name_url%', $repo); 23 | } 24 | 25 | /** 26 | * Prepare for DataTables 27 | */ 28 | public function indexPRE(Request $request) 29 | { 30 | $res = array_merge($this->loadCrudStyles(), [ 31 | 'model_name' => $this->path, 32 | ]); 33 | 34 | return (new %model%DataTable)->render('back._base.data-table', $res); 35 | } 36 | 37 | /** 38 | * Injects extra data to views. 39 | */ 40 | protected function getExtraData(): array 41 | { 42 | return []; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /stubs/DataTables/ExampleDataTable.php: -------------------------------------------------------------------------------- 1 | query()); 19 | return $records 20 | // ->eloquent($this->query()) 21 | ->addColumn('action', function ($record) { 22 | return view('back._base.data-table_actions', [ 23 | 'model_name' => '%model_name_url%', 24 | 'id' => $record->id, 25 | ]); 26 | }) 27 | ->rawColumns(['action']) 28 | 29 | ->make(true); 30 | } 31 | 32 | /** 33 | * Get the query object to be processed by datatables. 34 | * 35 | * @return \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder 36 | */ 37 | public function query() 38 | { 39 | $roles = %model%::query(); 40 | 41 | return $this->applyScopes($roles); 42 | } 43 | 44 | /** 45 | * Optional method if you want to use html builder. 46 | * 47 | * @return \Yajra\DataTables\Html\Builder 48 | */ 49 | public function html() 50 | { 51 | return $this->builder() 52 | ->columns($this->getColumns()) 53 | ->addAction(['width' => '10%']) 54 | ->ajax('') 55 | ->parameters([ 56 | 'dom' => 'Bfrtip', 57 | 'scrollX' => false, 58 | 'buttons' => [ 59 | 'print', 60 | 'reset', 61 | 'reload', 62 | [ 63 | 'extend' => 'collection', 64 | 'text' => ' Export', 65 | 'buttons' => [ 66 | 'csv', 67 | 'excel', 68 | 'pdf', 69 | ], 70 | ], 71 | 'colvis' 72 | ] 73 | ]); 74 | } 75 | 76 | /** 77 | * Get columns. 78 | * 79 | * @return array 80 | */ 81 | private function getColumns() 82 | { 83 | return [ 84 | 'slug' => ['name' => 'slug', 'data' => 'slug'], 85 | 'name' => ['name' => 'name', 'data' => 'name'], 86 | 'title' => ['name' => 'title', 'data' => 'title'], 87 | ]; 88 | } 89 | 90 | /** 91 | * Get filename for export. 92 | * 93 | * @return string 94 | */ 95 | protected function filename() 96 | { 97 | return '%model_name_url%'; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /stubs/Interactions/ExampleCreate.php: -------------------------------------------------------------------------------- 1 | 'required', 19 | ]); 20 | } 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function handle($id, array $data) 26 | { 27 | // $data['slug'] = str_slug(array_get($data, 'name')); 28 | 29 | return Larapp::interact( 30 | %model%Repository::class.'@update', 31 | [$id, $data] 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /stubs/Repositories/ExampleRepository.php: -------------------------------------------------------------------------------- 1 | model::orderBy('id', 'desc'); 23 | $qTerm = $request->filled('q') ? $request->get('q') : null; 24 | 25 | if ($qTerm) { 26 | $query->where('name', 'like', '%' . $qTerm . '%'); 27 | foreach ($this->attrsFilter as $key) { 28 | $query->orWhere($key, 'like', '%' . $qTerm . '%'); 29 | } 30 | } 31 | // logi($query->toSql()); 32 | 33 | return $query->paginate($perPage); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /stubs/config/settings/contact.php: -------------------------------------------------------------------------------- 1 | 'Company name', 3 | 'phone' => '(+34) 952 92 92 92', 4 | 'phone_link' => '+34952929292', 5 | 'mobile' => '(+34) 600 22 33 11', 6 | 'mobile_link' => '+34600223311', 7 | 'address_short' => 'Street name 4, B.2, 221177 Andalucia', 8 | 'address_formated' => 'Street name,
Block 2,
221177 Andalucia,
Spain', 9 | 'horario' => 'Monday a Viernes: de 9h a 13:30 y de 16:30 A 20h
Sábados: de 10h a 13:30', 10 | 'email_address' => 'info@example.com', 11 | 'google_maps_url' => '', 12 | 'google_analytics_key' => '', 13 | ]; 14 | -------------------------------------------------------------------------------- /stubs/config/settings/forms.php: -------------------------------------------------------------------------------- 1 | 'no-reply@example.com', 3 | 'from_email_address' => 'no-reply@example.com', 4 | 'notification_email_address' => 'admin@example.com', 5 | ]; 6 | -------------------------------------------------------------------------------- /stubs/config/settings/maps.php: -------------------------------------------------------------------------------- 1 | '12', 3 | 'latitude' => '16.430889', 4 | 'longitude' => '-5.166895', 5 | 'maps_marker_image' => '/images/marker.png', 6 | 'google_place_id' => '', 7 | 'google_maps_key' => env('MAPS_KEY'), 8 | ]; 9 | -------------------------------------------------------------------------------- /stubs/config/settings/social.php: -------------------------------------------------------------------------------- 1 | 'https://www.facebook.com/', 3 | 'twitter' => 'https://twitter.com/', 4 | 'linkedin-in' => 'http://www.linkedin.com/', 5 | 'google-plus-g' => '#none', 6 | 'instagram' => '', 7 | 'pinterest-p' => '', 8 | 'vimeo-v' => '', 9 | 'youtube' => '', 10 | ]; 11 | -------------------------------------------------------------------------------- /stubs/krud/create.blade.php: -------------------------------------------------------------------------------- 1 | @extends('%base_layout%') 2 | 3 | @section('content') 4 |
5 | @card(['title' => 'New ' . title_case($model_name)]) 6 | {!! Former::open_for_files()->route($model_name.'.store') !!} 7 | 8 | @includeIf($viewsBasePath.$model_name.'.form') 9 | {!! Former::close() !!} 10 | @endcard 11 |
12 | @endsection 13 | -------------------------------------------------------------------------------- /stubs/krud/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('%base_layout%') 2 | 3 | @section('content') 4 |
5 | @card() 6 | {!! Former::open_for_files() 7 | ->route($model_name . '.update', $record ) 8 | ->populate( $record ) 9 | !!} 10 | 11 | @includeIf($viewsBasePath.$model_name.'.form', ['submitButtonText' => 'Update']) 12 | {!! Former::close() !!} 13 | @endcard 14 |
15 | @endsection 16 | -------------------------------------------------------------------------------- /stubs/krud/form.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | {!! Former::text('name')->required()->label('Name') !!} 4 |
5 |
6 | {!! Former::email('email')->required()->label('Email') !!} 7 |
8 |
9 | {!! Former::files('img')->accept('image/jpeg', 'image/png') !!} 10 |
11 |
12 | @include('klaravel::ui.forms.radios',[ 13 | 'items' => ['1' => 'Yes', '0' => 'No'], 14 | 'label' => 'Online', 15 | 'name' => 'online', 16 | 'value' => isset($record) ? $record->online : '', 17 | ]) 18 |
19 |
20 | 21 | @include('klaravel::ui.forms.textarea',[ 22 | 'name' => 'excerpt', 23 | 'label' => 'Short description', 24 | 'rows' => 2 25 | ]) 26 | 27 | @include('klaravel::ui.forms.textarea',[ 28 | 'name' => 'text', 29 | 'label' => 'Description', 30 | ]) 31 | 32 | 33 | @include('klaravel::ui.forms.buttons') 34 | -------------------------------------------------------------------------------- /stubs/krud/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('%base_layout%') 2 | 3 | @section('content') 4 |
5 | @card(['title' => 'Listing ' . title_case(str_plural($model_name))]) 6 | @includeIf('klaravel::ui.tables.actions-menu') 7 | @if ($records->total()>0) 8 | @includeIf('klaravel::ui.tables.pagination',['class'=> 'py-2 mt-2']) 9 |
10 | 11 | @includeIf($viewsBasePath.$model_name.'.table') 12 |
13 | @else 14 | @includeif('klaravel::_parts.no-records') 15 | @endif 16 | @endcard 17 |
18 | @endsection 19 | -------------------------------------------------------------------------------- /stubs/krud/table.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | @foreach($records as $item) 14 | 15 | 16 | 21 | 22 | 23 | @include('klaravel::ui.tables.actions', ['size' => 'sm']) 24 | 25 | @endforeach 26 | 27 |
@includeIf('klaravel::ui.tables.count')
Name
{{ $item->id }} 17 | 18 | 19 | 20 | {{ $item->name }}{{ isset($item->created_at)? $item->created_at->diffForHumans():'-'}}
28 | -------------------------------------------------------------------------------- /stubs/routes/crud.stub: -------------------------------------------------------------------------------- 1 | /** 2 | * %modelo% Krud Routes 3 | */ 4 | $router->get('%prefixed%%keyname%', ['uses' => '%folder%%modelo%Controller@index', 'as' => '%prefix%%keyname%.index']); 5 | $router->get('%prefixed%%keyname%/{id:[\d]+}', ['uses' => '%folder%%modelo%Controller@index', 'as' => '%prefix%%keyname%.show']); 6 | $router->post('%prefixed%%keyname%', ['uses' => '%folder%%modelo%Controller@index', 'as' => '%prefix%%keyname%.store']); 7 | $router->put('%prefixed%%keyname%/{id:[\d]+}', ['uses' => '%folder%%modelo%Controller@index', 'as' => '%prefix%%keyname%.update']); 8 | $router->delete('%prefixed%%keyname%/{id:[\d]+}', ['uses' => '%folder%%modelo%Controller@index', 'as' => '%prefix%%keyname%.destroy']); 9 | -------------------------------------------------------------------------------- /stubs/routes/resource.stub: -------------------------------------------------------------------------------- 1 | lumen_resource($router, '%prefixed%%keyname%', '%prefix%%keyname%', '%folder%%modelo%Controller'); 2 | -------------------------------------------------------------------------------- /stubs/swagger/property.stub: -------------------------------------------------------------------------------- 1 | * @SWG\Property( 2 | * property="first_name", 3 | * type="string", 4 | * description="%model%'s first name", 5 | * example="John" 6 | * ), 7 | -------------------------------------------------------------------------------- /wiki/README.md: -------------------------------------------------------------------------------- 1 | # WIKI 2 | 3 | ```php 4 | /* 5 | | Klaravel user guide + scaffold generator 6 | | 7 | | Local URL: http://localhost:8000/klaravel/wiki/scaffold 8 | | Local Markdown: open vendor/ksoft/klaravel/wiki 9 | | Online Markdown: https://github.com/kikoseijo/klaravel/tree/master/wiki 10 | | _______________________________________ 11 | */ 12 | ``` 13 | 14 | --- 15 | 16 |
!Happy Days
17 | -------------------------------------------------------------------------------- /wiki/components-vue.md: -------------------------------------------------------------------------------- 1 | # Vue components 2 | 3 | To be able to use this components you must do a little configuration on your webpack. 4 | 5 | #### Webpack configuration 6 | 7 | ``` 8 | .webpackConfig({ 9 | resolve: { 10 | symlinks: false, 11 | modules: [ 12 | path.resolve( 13 | __dirname, 'vendor/ksoft/klaravel/resources/assets/js'), 14 | 'node_modules' 15 | ], 16 | alias: { 17 | 'vue$': 'vue/dist/vue.js', 18 | '~': path.join(__dirname, './resources/assets/js'), 19 | '@': path.join(__dirname, './resources/assets/js/components') 20 | } 21 | } 22 | }) 23 | ``` 24 | 25 | After configure, webpack should be able to resolve the component, `require('klaravel');` should 26 | give you no errors if everything its fine. 27 | 28 | ```js 29 | import ElementUI from 'element-ui'; 30 | import locale from 'element-ui/lib/locale/lang/es'; 31 | Vue.use(ElementUI, { locale }); 32 | 33 | import Notify from 'vue-notifyjs'; 34 | Vue.use(Notify, { type: 'danger', timeout: 2000 }); 35 | 36 | require('klaravel'); // <----------This is the line you need add. 37 | import '~/../sass/element_variables.scss'; 38 | ``` 39 | 40 | ```scss 41 | /* element_variables.scss */ 42 | /* icon font path, required */ 43 | $--font-path: '~element-ui/lib/theme-chalk/fonts'; 44 | @import '~element-ui/packages/theme-chalk/src/index'; 45 | ``` 46 | 47 | #### Media upload 48 | 49 | ``` 50 | 55 | 56 | // this.uploadUrl = this.baseUrl + '?_token=' + Larapp.csrfToken; 57 | ``` 58 | 59 | #### Select component 60 | 61 | ``` 62 | 69 | 70 | ``` 71 | 72 | Example use: 73 | 74 | ``` 75 |
76 | 77 | 83 | 84 |
85 | ``` 86 | 87 | `props: [ 'value', 'name', 'options', 'placeholder', 'searchable', 'multiple', 'clearable', 'collapseTags' ],` 88 | 89 | #### Slider - Range slider 90 | 91 | ``` 92 | 98 | 99 | ``` 100 | -------------------------------------------------------------------------------- /wiki/components-widgets.md: -------------------------------------------------------------------------------- 1 | # Widgets 2 | 3 | All this Widgets are based on Bootstrap4, additional configuration can be done by the use 4 | of predefined classes, you can find more in the [official Bootstrap4 documentation](https://getbootstrap.com/docs/4.0/components/). 5 | 6 | #### Alert 7 | 8 | ``` 9 | @component('klaravel::ui.alert', [ 10 | 'title' => 'Alert title', 11 | 'type' => 'warning', 12 | 'class' => 'my-3', 13 | ]) 14 | This is my message for the alert 15 | @endcomponent 16 | ``` 17 | 18 | #### Badge 19 | 20 | ``` 21 | @component('klaravel::ui.badge', ['type' => 'primary']) 22 | {{$marca->name}} 23 | @endcomponent 24 | ``` 25 | 26 | #### Card 27 | 28 | ``` 29 | @card([ 30 | 'title' => 'Klaravel control center', 31 | 'reload_btn' => true, 32 | 'tabs' => ['en' => 'English', 'es' => 'Spanish'], // Yes you can trigger tabs. 33 | 'style' => 'margin-top:62px;', 34 | 'class' => 'mb-4' 35 | ]) 36 | @include('back.users.multilingue-form') 37 | @endcard 38 | ``` 39 | 40 | #### Figure 41 | 42 | ``` 43 | @component('klaravel::ui.figure', [ 44 | 'class' => 'my-5', 45 | 'caption' => 'This is the media descripion.' 46 | ]) 47 | {{$marca->name}} 48 | @endcomponent 49 | ``` 50 | 51 | #### List group 52 | 53 | ``` 54 | @component('klaravel::ui.list-group', [ 55 | 'class' => 'my-5', 56 | 'items' => ['item 1', 'item 2'] 57 | ]) 58 |
  • Off array item
  • 59 | @endcomponent 60 | ``` 61 | 62 | #### Carousel 63 | 64 | ``` 65 | @include('klaravel::ui.carousel', [ 66 | 'id' => 'myCarousel1', 67 | 'class' => 'my-5', 68 | 'controls' => true, 69 | 'indicators' => true, 70 | 'items' => [ 71 | 'First slide', 72 | 'First slide', 73 | 'First slide', 74 | ] 75 | ]) 76 | ``` 77 | 78 | #### Modal 79 | 80 | ``` 81 | @component('klaravel::ui.modal', [ 82 | 'title' => 'My modal title', 83 | 'modalId' => 'myComponentModal', 84 | 'size' => 'lg' 85 | ]) 86 | @includeIf('parts.modal-with-form-body') 87 | @endcomponent 88 | ``` 89 | 90 | And this could be the body of your modal on a separate file `parts/modal-with-form-body.blade.php` 91 | 92 | ``` 93 | {!! Former::open()->route('contact.submit')->id('my-modal-form') !!} 94 | 97 | 100 | {!! Former::close() !!} 101 | ``` 102 | 103 | #### Tab 104 | 105 | ``` 106 | @component('klaravel::ui.tab', [ 107 | 'tabs' => [ 108 | 'settings' => 'Settings', 109 | 'photos' => ' Photos' 110 | ] 111 | ]) 112 |
    113 | {!! Former::open() 114 | ->route($model_name . '.update', $record ) 115 | ->populate( $record ) 116 | ->open_for_files() !!} 117 | @include ('backend.'.$model_name.'.form', ['submitButtonText' => 'Update records']) 118 | {!! Former::close() !!} 119 |
    120 |
    121 | @include('backend.'.$model_name.'.media') 122 |
    123 | @endcomponent 124 | ``` 125 | 126 | #### Card Deck (Media) 127 | 128 | ``` 129 | 130 | ``` 131 | -------------------------------------------------------------------------------- /wiki/formers.md: -------------------------------------------------------------------------------- 1 | For more detailed info visit [Formers Github](https://github.com/formers/former/wiki/) 2 | 3 | #### Configuration 4 | 5 | Adjust configuration file `config/former.php` with the following information: **this is due to bootstrap4 not being a framework available right now** i got yo covered... 6 | 7 | ``` 8 | // The default form type 9 | 'default_form_type' => 'vertical', 10 | // The framework to be used by Former 11 | 'framework' => 'Ksoft\Klaravel\Utils\FormerBootstrap4', 12 | 'FormerBootstrap4' => array( 13 | // Width of labels for horizontal forms expressed as viewport => grid columns 14 | 'labelWidths' => array( 15 | 'large' => 2, 16 | 'small' => 10, 17 | ), 18 | ``` 19 | 20 | Checkboxes and radios having issues with alignments, use the components ?? by hand... 21 | 22 | #### Create record 23 | 24 | ```php 25 | {!! Former::open_for_files() 26 | ->route($model_name.'.store') 27 | !!} 28 | ... 29 | {!! Former::text('name')->required()->label('Name') !!} 30 | @include('klaravel::ui.forms.textarea',[ 31 | 'name' => 'excerpt', 32 | 'label' => 'Short description', 33 | 'rows' => 2 34 | ]) 35 | ... 36 | @include('klaravel::ui.forms.buttons') 37 | {!! Former::close() !!} 38 | ``` 39 | 40 | #### Update record 41 | 42 | ```php 43 | {!! Former::open_for_files() 44 | ->route($model_name . '.update', $record ) 45 | ->populate( $record ) 46 | !!} 47 | ... 48 | {!! Former::text('name')->required()->label('Name') !!} 49 | @include('klaravel::ui.forms.textarea',[ 50 | 'name' => 'excerpt', 51 | 'label' => 'Short description', 52 | 'rows' => 2 53 | ]) 54 | ... 55 | @include('klaravel::ui.forms.buttons', ['submitButtonText' => 'Update record']) 56 | {!! Former::close() !!} 57 | ``` 58 | 59 | #### Select fromQuery 60 | 61 | ```php 62 | {!! Former::select('post_id') 63 | ->fromQuery(App\Models\Post::orderBy('name','asc')->get(), 'name', 'id') 64 | ->required() 65 | ->placeholder('Select...') 66 | ->label('Post') 67 | !!} 68 | ``` 69 | 70 | #### Select options 71 | 72 | ```php 73 | {!! Former::select('post_id') 74 | ->options(['Option 1', 'Option 2'], null, true) 75 | ->placeholder('Select...') 76 | ->label('Post') 77 | !!} 78 | ``` 79 | 80 | ```php 81 | {!! Former::select('rating') 82 | ->options(array_combine(range(1,5),range(1,5))) 83 | ->label('Rating') 84 | ->placeholder('Select rating') 85 | !!} 86 | ``` 87 | 88 | #### Radio buttons 89 | 90 | This is a temporary fix due to Formers being outdated at the moment. 91 | 92 | ```php 93 | @include('klaravel::ui.forms.radios',[ 94 | 'items' => ['1' => 'Yes', '0' => 'No'], 95 | 'label' => 'Record active', 96 | 'name' => 'active', 97 | 'value' => isset($record) ? $record->active : '', 98 | ]) 99 | ``` 100 | 101 | #### Textarea 102 | 103 | ``` 104 | @include('klaravel::ui.forms.textarea',[ 105 | 'name' => 'excerpt', 106 | 'label' => 'Short description', 107 | 'rows' => 2 108 | ]) 109 | ``` 110 | 111 | #### files 112 | 113 | ``` 114 | {!! Former::file('img') 115 | ->label('Slider image') 116 | ->accept('image/jpeg', 'image/png') 117 | ->help('Recommended image size 1600x840 px.') 118 | !!} 119 | ``` 120 | 121 | #### Form buttons 122 | 123 | ``` 124 | @include('klaravel::ui.forms.buttons') 125 | ``` 126 | -------------------------------------------------------------------------------- /wiki/helpers-backups.md: -------------------------------------------------------------------------------- 1 | # Backups 2 | 3 | Backups are integrated into kLaravel thanks to [**Spatie laravel-backup**](https://docs.spatie.be/laravel-backup) 4 | 5 | ### Publish configuration 6 | 7 | ```php 8 | php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider" 9 | ``` 10 | 11 | now you can configure the email where to send notifications when backups are done and also remove unneccesary folders on backups. 12 | 13 | ```php 14 | 'exclude' => [ 15 | base_path('vendor'), 16 | base_path('node_modules'), 17 | base_path('tests'), 18 | base_path('storage/debugbar'), 19 | base_path('storage/logs'), 20 | base_path('.git'), 21 | base_path('.gtm'), 22 | base_path('storage/app/APPP-NAME-BACKUPS'), 23 | base_path('Envoy.blade.php'), 24 | base_path('.ftpconfig'), 25 | base_path('.env'), 26 | ], 27 | ``` 28 | 29 | ### Scheduling 30 | 31 | ```php 32 | // app/Console/Kernel.php 33 | 34 | protected function schedule(Schedule $schedule) 35 | { 36 | $schedule->command('backup:clean')->daily()->at('01:00'); 37 | $schedule->command('backup:run')->daily()->at('02:00'); 38 | } 39 | ``` 40 | 41 | ### Klaravel 42 | 43 | This is a typical setting for a full access to backups module integrated in kLaravel. 44 | 45 | ```php 46 | // config/ksoft.php 47 | 'module' => [ 48 | 'backup' => [ // https://github.com/spatie/laravel-backup route('kBackup.index') 49 | 'enabled' => true, 50 | 'route_name' => 'back/backup', 51 | 'can_see_full_backups' => true, // activate only when full access 52 | 'middleware' => ['web','auth', 'role:superadmin'], 53 | 'extra_arguments' => [ 54 | // '--only-db' => 'true', // comment this line to allow file backups. 55 | ], 56 | ], 57 | ``` 58 | -------------------------------------------------------------------------------- /wiki/helpers-commons.md: -------------------------------------------------------------------------------- 1 | # Integration helpers 2 | 3 | Quick access instruccions 4 | 5 | ###### Klaravel nav button 6 | 7 | ```php 8 | @includeif('klaravel::_parts.menu.klara') 9 | ``` 10 | 11 | ###### Envoy template configuration 12 | 13 | Used for quick and easy remote install and deploy. 14 | 15 | [https://gist.github.com/kikoseijo/205c49fbc66aba03bbb6d3ff456124ef](https://gist.github.com/kikoseijo/205c49fbc66aba03bbb6d3ff456124ef) 16 | -------------------------------------------------------------------------------- /wiki/helpers-functions.md: -------------------------------------------------------------------------------- 1 | # Helper functions 2 | 3 | All helper functions are declared with a `function_exists` conditional. 4 | 5 | ```php 6 | // Lowercases the string. 7 | function normalizeString($text, $limit): string {} 8 | 9 | // Mardown converter 10 | function do_markdown($markdown): string {} 11 | 12 | // Model name to title_case replacing '_' with spaces 13 | function model_title($modelName): string {} 14 | 15 | // Pretty print arrays 16 | function pretty_print_array(array $array_data): string {} 17 | 18 | // Human readable using JenssDate (Not installed) 19 | function diff_date_for_humans(Carbon $date): string {} 20 | // $item->created_at->diffForHumans() // using Carbon instead of JenssDate 21 | 22 | // Resource route for Lumen 23 | function resource($path, $controller, $name, $exclude = []) {} 24 | 25 | // Human readable size 26 | function humanReadableSize($bites): string {} 27 | 28 | // Carbon date from timestamp 29 | function createFromTimestamp($timestamp): string {} 30 | 31 | // Dump database queries 32 | function dbDump($simple = true): string {} 33 | 34 | // Lumen path helpers 35 | function config_path($path = ''): string {} 36 | function app_path($path = ''): string {} 37 | function public_path($path = ''): string {} 38 | 39 | // Debug, simple shortcodes 40 | function logi($data): void {} // info 41 | function loge($data): void {} // error 42 | function logc($data): void {} // critical 43 | ``` 44 | -------------------------------------------------------------------------------- /wiki/helpers-mailables.md: -------------------------------------------------------------------------------- 1 | # Mailables 2 | 3 | #### Overwrite mail settings at runtime 4 | 5 | ``` 6 | config(['mail.from.address' => settings('forms.from_email_address')]); 7 | config(['mail.from.name' => settings('forms.from_name')]); 8 | ``` 9 | -------------------------------------------------------------------------------- /wiki/helpers-passport.md: -------------------------------------------------------------------------------- 1 | # Laravel passport 2 | 3 | #### Install 4 | 5 | ``` 6 | php artisan migrate 7 | php artisan migrate 8 | ``` 9 | 10 | Full Passport features installation method. 11 | 12 | ``` 13 | php artisan passport:install 14 | ``` 15 | 16 | Simple token client installation method use `--password` option 17 | for the Password Grant Client- 18 | 19 | ``` 20 | php artisan passport:keys // Necessary on first deploy to server 21 | // one of the 2 options. 22 | php artisan passport:client 23 | php artisan passport:client --password 24 | ``` 25 | 26 | #### Configuration 27 | 28 | On user model add the HasApiTokens trait. 29 | 30 | ```php 31 | use Laravel\Passport\HasApiTokens; 32 | ``` 33 | 34 | On service provider **boot method** 35 | 36 | ``` 37 | use Laravel\Passport\Passport; 38 | ... 39 | Passport::routes(); 40 | // Passport::tokensExpireIn(now()->addDays(15)); 41 | // Passport::refreshTokensExpireIn(now()->addDays(30)); 42 | Passport::ignoreMigrations(); // register method 43 | ``` 44 | 45 | on `config/auth.php` api driver to passport 46 | 47 | ``` 48 | 'api' => [ 49 | 'driver' => 'passport', 50 | 'provider' => 'users', 51 | ], 52 | ``` 53 | 54 | Publish the Passport Vue components 55 | 56 | ``` 57 | php artisan vendor:publish --tag=passport-components 58 | ``` 59 | 60 | #### Graphql login example 61 | 62 | Token grant example for graphql resolver function. 63 | 64 | ```php 65 | use Illuminate\Auth\Access\AuthorizationException; 66 | ... 67 | public function resolve($root, $args, $context, ResolveInfo $info) 68 | { 69 | $user = User::where('email', $args['email'])->first(); 70 | 71 | if ($user && app('hash')->check($args['password'], $user->password)) { 72 | $this->deleteExpiredTokens($user); 73 | $user['token'] = $user->createToken('LRHP')->accessToken; 74 | return $user; 75 | } 76 | throw new AuthorizationException('Invalid credentials!'); 77 | return null; 78 | } 79 | 80 | protected function deleteExpiredTokens($user) 81 | { 82 | $user->tokens()->where('expires_at', '<=', Carbon::now())->delete(); 83 | } 84 | ``` 85 | 86 | #### UnauthorizedHttpException 87 | 88 | ```php 89 | namespace App\Exceptions; 90 | 91 | use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; 92 | 93 | class InvalidCredentialsException extends UnauthorizedHttpException 94 | { 95 | public function __construct($message = null, \Exception $previous = null, $code = 0) 96 | { 97 | parent::__construct('', $message, $previous, $code); 98 | } 99 | } 100 | ``` 101 | 102 | #### Login Mutation for React-relay 103 | 104 | ```js 105 | // @flow 106 | import { commitMutation, graphql } from 'react-relay'; 107 | import RelayEnv from './../../../graphql/AuthEnviroment'; 108 | 109 | const environment = RelayEnv.environment; 110 | 111 | const mutation = graphql` 112 | mutation LoginMutation($email: String!, $password: String!) { 113 | login(email: $email, password: $password) { 114 | token 115 | user { 116 | id 117 | } 118 | } 119 | } 120 | `; 121 | 122 | export default ( 123 | email: string, 124 | password: string, 125 | callback: Function, 126 | onError: Function 127 | ) => { 128 | const variables = { 129 | email, 130 | password 131 | }; 132 | 133 | commitMutation(environment, { 134 | mutation, 135 | variables, 136 | onCompleted: (response, error) => { 137 | if (response.login && response.login.token) { 138 | const token = response.login.token; 139 | callback(null, token); 140 | } else { 141 | onError(error); 142 | } 143 | }, 144 | onError 145 | }); 146 | }; 147 | ``` 148 | -------------------------------------------------------------------------------- /wiki/helpers-seeds.md: -------------------------------------------------------------------------------- 1 | # Seeds reference 2 | 3 | #### User seeder 4 | 5 | ``` 6 | php artisan make:seeder UsersTableSeeder 7 | ``` 8 | 9 | ``` 10 | if (! DB::table('users')->where('email', 'user@example.com')->first()) { 11 | DB::table('users')->insert([ 12 | 'name' => 'Kiko Seijo', 13 | 'email' => 'user@example.com', 14 | 'password' => app('hash')->make('secret'), 15 | 'created_at' => now(), 16 | 'updated_at' => now(), 17 | // 'admin' => 1, 18 | ]); 19 | } 20 | ``` 21 | 22 | #### Faker 23 | 24 | ``` 25 | use Faker\Factory; 26 | use Faker\Generator as Faker; 27 | use Faker\Provider\es_ES\Payment; 28 | 29 | 30 | $faker = Factory::create('es_ES'); 31 | ``` 32 | 33 | #### Faker most used 34 | 35 | ``` 36 | 'number_plate' => $faker->numerify('XA-####-NP'), 37 | 'reference' => $faker->word, 38 | 'chofer' => $faker->randomElement([NULL, $faker->word]), 39 | 'is_active' => $faker->boolean(), 40 | 'notes' => $faker->paragraph, 41 | 'created_at' => Carbon::now()->addMinutes(-rand(0, 60 * 24 * 7 * 4)), 42 | 'arrive_time' => $faker->time, 43 | 44 | // company 45 | 'name' => $faker->company, 46 | 'cif' => $faker->vat, // use Faker\Provider\es_ES\Payment; 47 | 'address' => $faker->address, 48 | 'phone' => $faker->phoneNumber, 49 | 'email' => $faker->safeEmail, 50 | 'calidad_name' => $faker->name, 51 | 'calidad_email' => $faker->safeEmail, 52 | 'notes' => $faker->paragraph, 53 | 54 | // not sure if this is faker ?? spatie seeder.- 55 | 'estado_id' => $faker->numberBetween(0,4), 56 | 'delivery_at' => $faker->dateTimeBetween('-30 days', '-2 days'), 57 | ``` 58 | 59 | #### Map Morph types 60 | 61 | ``` 62 | Relation::morphMap(config('app.post_types')); 63 | ``` 64 | -------------------------------------------------------------------------------- /wiki/helpers-seo.md: -------------------------------------------------------------------------------- 1 | # SEO reference guide 2 | -------------------------------------------------------------------------------- /wiki/helpers-sortable.md: -------------------------------------------------------------------------------- 1 | # Sortable 2 | 3 | ``` 4 | composer require spatie/eloquent-sortable 5 | ``` 6 | 7 | [spatie/eloquent-sortable official documentation](https://github.com/spatie/eloquent-sortable). 8 | 9 | #### Route 10 | 11 | ``` 12 | Route::get('MODEL_PATH_NAME/sort/{id}/{action?}', 'MODELController@sortRecord')->name('MODEL_PATH_NAME.sort'); 13 | ``` 14 | 15 | #### Controller 16 | 17 | ``` 18 | use Ksoft\Klaravel\Traits\CanSortRecords; 19 | ``` 20 | 21 | #### Model 22 | 23 | ```php 24 | use Spatie\EloquentSortable\Sortable; 25 | use Spatie\EloquentSortable\SortableTrait; 26 | 27 | class MyModel extends Eloquent implements Sortable 28 | { 29 | { 30 | 31 | use SortableTrait; 32 | // IMPORTANT: next line to trigger table action buttons. 33 | public $sortable = [ 34 | 'order_column_name' => 'order_column', 35 | 'sort_when_creating' => true, 36 | ]; 37 | 38 | ... 39 | } 40 | ``` 41 | 42 | #### What you can do... 43 | 44 | ``` 45 | $orderedRecords = MyModel::ordered()->get(); 46 | MyModel::setNewOrder([3,1,2]); 47 | $myModel->moveOrderDown(); 48 | $myModel->moveOrderUp(); 49 | $myModel->moveToStart(); 50 | $myModel->moveToEnd(); 51 | ``` 52 | 53 | More here [https://github.com/spatie/eloquent-sortable](https://github.com/spatie/eloquent-sortable) 54 | -------------------------------------------------------------------------------- /wiki/helpers-translatable.md: -------------------------------------------------------------------------------- 1 | # Translatable 2 | 3 | Full repo + documentation: [https://github.com/spatie/laravel-translatable](https://github.com/spatie/laravel-translatable) 4 | 5 | **Big thanks** to **[Spatie](https://spatie.be/en/opensource) team**, 6 | 7 | #### Installation 8 | 9 | ```bash 10 | composer require spatie/laravel-translatable 11 | php artisan vendor:publish --provider="Spatie\Translatable\TranslatableServiceProvider" 12 | ``` 13 | 14 | #### Model 15 | 16 | ```php 17 | use Illuminate\Database\Eloquent\Model; 18 | use Spatie\Translatable\HasTranslations; 19 | 20 | class NewsItem extends Model 21 | { 22 | use HasTranslations; 23 | 24 | public $translatable = ['name']; 25 | } 26 | ``` 27 | 28 | #### Helpers 29 | 30 | ```php 31 | // GET 32 | public function getTranslation(string $attributeName, string $locale) : string 33 | $newsItem->getTranslation('title','es'); 34 | public function getTranslations(string $attributeName): array 35 | $newsItem->getTranslations(); 36 | 37 | // SET 38 | public function setTranslation(string $attributeName, string $locale, string $value) 39 | $newsItem->setTranslation('name', 'en', 'Updated name in English'); 40 | public function setTranslations(string $attributeName, array $translations); 41 | 42 | // REMOVE 43 | public function forgetTranslation(string $attributeName, string $locale); 44 | public function forgetAllTranslations(string $locale); 45 | 46 | // SEARCH 47 | NewsItem::where('name->en', 'Name in English')->get(); 48 | 49 | foreach ($this->getTranslatableAttributes() as $name) { 50 | $attributes[$name] = $this->getTranslation($name, app()->getLocale()); 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /wiki/helpers-translate.md: -------------------------------------------------------------------------------- 1 | # Translatable 2 | 3 | #### LocaleServiceProvider 4 | 5 | ``` 6 | app->setLocale(CurrentLocale::determine()); 21 | 22 | Date::setLocale($locale); 23 | } 24 | } 25 | ``` 26 | 27 | #### CurrentLocale 28 | 29 | ``` 30 | request->segment(1); 43 | 44 | if (static::isValidLocale($urlLocale)) { 45 | return $urlLocale; 46 | } 47 | 48 | try { 49 | $cookieLocale = app(Encrypter::class)->decrypt(request()->cookie('locale')); 50 | 51 | if (self::isValidLocale($cookieLocale)) { 52 | return $cookieLocale; 53 | } 54 | } catch (Exception $exception) { 55 | } 56 | 57 | $browserLocale = collect(request()->getLanguages())->first(); 58 | 59 | if (self::isValidLocale($browserLocale)) { 60 | return $browserLocale; 61 | } 62 | 63 | return app()->getLocale(); 64 | } 65 | 66 | public static function getContentLocale(): string 67 | { 68 | if (! static::isValidLocale(locale())) { 69 | return config('app.locales')[0]; 70 | } 71 | 72 | return locale(); 73 | } 74 | 75 | public static function isValidLocale($locale): bool 76 | { 77 | if (! is_string($locale)) { 78 | return false; 79 | } 80 | 81 | $locales = config('app.locales'); 82 | 83 | return in_array($locale, $locales); 84 | } 85 | } 86 | ``` 87 | -------------------------------------------------------------------------------- /wiki/helpers-validations.md: -------------------------------------------------------------------------------- 1 | # Laravel validations 2 | 3 | Some mostly used rules at a handy place. 4 | 5 | ```php 6 | public function validator($id, array $data) 7 | { 8 | return Validator::make($data, [ 9 | 'text.en' => 'required|string', 10 | 'group' => 'required|string|max:255', 11 | // Unique when updating. 12 | 'key' => 'required|string|unique:fragments,key,'.$id, 13 | ]); 14 | } 15 | ``` 16 | -------------------------------------------------------------------------------- /wiki/krud-policy.md: -------------------------------------------------------------------------------- 1 | # Resource policies 2 | 3 | `php artisan make:policy RecordsPolicy` 4 | 5 | ### Base Policy (debug) 6 | 7 | ```php 8 | namespace App\Policies; 9 | 10 | use App\User; 11 | // use App\Policies\Traits\RootPolicyFilter; 12 | use Illuminate\Auth\Access\HandlesAuthorization; 13 | 14 | class RecordsPolicy 15 | { 16 | use HandlesAuthorization; 17 | // use RootPolicyFilter; 18 | 19 | public function view(User $user, $record) 20 | { 21 | // logi('RecordsPolicy: view + show'); 22 | return true; 23 | 24 | } 25 | 26 | public function create(User $user) 27 | { 28 | // logi('RecordsPolicy: create + store'); 29 | return true; 30 | } 31 | 32 | public function update(User $user, $record) 33 | { 34 | // logi('RecordsPolicy: update + edit'); 35 | return true; 36 | } 37 | 38 | public function delete(User $user, $record) 39 | { 40 | // logi('RecordsPolicy: delete'); 41 | return true; 42 | } 43 | } 44 | ``` 45 | 46 | ### Policy Filter trait (for admins) 47 | 48 | ```php 49 | namespace App\Policies\Traits; 50 | 51 | /** 52 | * Trait RootPolicyFilter. 53 | */ 54 | trait RootPolicyFilter 55 | { 56 | public function before($user, $ability) 57 | { 58 | // logi('before__'.$ability); 59 | // if ($user->isAdmin()) { 60 | // return true; 61 | // } 62 | } 63 | } 64 | ``` 65 | 66 | ### Route Service Provider 67 | 68 | `App\Providers\RouteServiceProvider.php` 69 | 70 | ``` 71 | ... 72 | public function boot() 73 | { 74 | // 75 | 76 | parent::boot(); 77 | 78 | Route::model('company', 'App\Models\Company'); 79 | Route::model('user', 'App\Models\User'); 80 | } 81 | ``` 82 | 83 | #### Auth Service Provider 84 | 85 | `App\Providers\AuthServiceProvider.php` 86 | 87 | ``` 88 | ... 89 | protected $policies = [ 90 | 'App\Models\Company' => 'App\Policies\RecordsPolicy', 91 | ]; 92 | ``` 93 | 94 | #### Personalize resource param name 95 | 96 | On your controller `__construct`, third parameter. 97 | 98 | ``` 99 | public function __construct(CompanyRepository $repo) 100 | { 101 | $this->createInteraction = CompanyCreate::class; 102 | $this->updateInteraction = CompanyUpdate::class; 103 | 104 | parent::__construct('company', $repo, 'CONFIGURE_PARAM_NAME_HERE'); 105 | } 106 | ``` 107 | 108 | On base controller you should call: 109 | 110 | ```php 111 | public function __construct($path, $repo, $param='') 112 | { 113 | $this->authorizeResource($repo->model(), $param); // this is the important line. 114 | ``` 115 | -------------------------------------------------------------------------------- /wiki/krud-views.md: -------------------------------------------------------------------------------- 1 | # Krud base layouts 2 | 3 | This are reusable layouts for the krud component, them here for you if you need to overwrite them, just copy and paste 4 | inside you component folder and the BaseKrudController will defaults to your files if found. 5 | 6 | #### Table view 7 | 8 | `index.blade.php` 9 | 10 | ``` 11 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 12 | 13 | @section('content') 14 |
    15 | @card(['title' => 'Listing ' . title_case(str_plural($model_name))]) 16 | @includeIf('klaravel::ui.tables.actions-menu') 17 | @if ($records->total()>0) 18 | @includeIf('klaravel::ui.tables.pagination',['class'=> 'py-2 mt-2']) 19 |
    20 | @includeIf($viewsBasePath.$model_name.'.table') 21 |
    22 | @else 23 | @includeif('klaravel::_parts.no-records') 24 | @endif 25 | @endcard 26 |
    27 | @endsection 28 | ``` 29 | 30 | #### Create view 31 | 32 | `create.blade.php` 33 | 34 | ``` 35 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 36 | 37 | @section('content') 38 |
    39 | @card(['title' => 'New ' . title_case($model_name)]) 40 | {!! Former::open_for_files()->route($model_name.'.store') !!} 41 | @includeIf($viewsBasePath.$model_name.'.form') 42 | {!! Former::close() !!} 43 | @endcard 44 |
    45 | @endsection 46 | ``` 47 | 48 | #### Edit 49 | 50 | `edit.blade.php` 51 | 52 | ``` 53 | @extends(config('ksoft.module.crud.layout', 'klaravel::layouts.crud')) 54 | 55 | @section('content') 56 |
    57 | @card() 58 | {!! Former::open_for_files() 59 | ->route($model_name . '.update', $record ) 60 | ->populate( $record ) 61 | !!} 62 | @includeIf($viewsBasePath.$model_name.'.form', ['submitButtonText' => 'Update']) 63 | {!! Former::close() !!} 64 | @endcard 65 |
    66 | @endsection 67 | ``` 68 | 69 | #### Additional tips 70 | 71 | When you overwrite the views to customize to your needs you get extra capabilities, by using the Laravel Blade power engine 72 | you can push pieces of code to your header and footer. Check out the Layout to see all possibilities. 73 | 74 | This is just an use example, we adding animate.css to the header stylesheet stack, and swall to the footer scripts stack. 75 | 76 | ``` 77 | @push('stylesheets') 78 | 79 | @endpush 80 | ``` 81 | 82 | ``` 83 | @push('scripts') 84 | 89 | @endpush 90 | ``` 91 | 92 | Explore the available components to have extra control on things like adding buttons 93 | to tables using the `klaravel::ui.tables.actions`, adding dropdowns and buttons to `klaravel::ui.tables.actions-menu` you will benefit on doing less code and producing better quality and faster code development. 94 | 95 |   96 | 97 | Happy coding! 98 | -------------------------------------------------------------------------------- /wiki/layouts-footer.md: -------------------------------------------------------------------------------- 1 | # The Footer 2 | 3 | Use this template to overwrite your own implementation with small customizations. 4 | 5 | ```html 6 | 42 | ``` 43 | 44 | #### Basic css 45 | 46 | ```css 47 | footer { 48 | color: #6f6d70; 49 | font-size: 0.9em; 50 | a { 51 | color: #6f6d70; 52 | } 53 | .footer__version { 54 | float: left; 55 | text-align: left; 56 | } 57 | .footer__credits { 58 | float: right; 59 | text-align: center; 60 | } 61 | .footer__brand { 62 | width: 2.3em; 63 | margin-right: 12px; 64 | height: auto; 65 | vertical-align: middle; 66 | } 67 | } 68 | 69 | @media (max-width: 640px) { 70 | .footer__version { 71 | float: none; 72 | } 73 | .footer__credits { 74 | float: none; 75 | } 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /wiki/layouts-settings.md: -------------------------------------------------------------------------------- 1 | # Settings menu 2 | 3 | ``` 4 | @include('klaravel::_parts.menu.settings') 5 | ``` 6 | 7 | ```php 8 | @if(isset($settings_menu) && isset($settings_menu_enabled)) 9 | // 10 | @if ($settings_menu_enabled) 11 | @foreach ($settings_menu as $menuTitle => $menuItems) 12 | @if (is_array($menuItems)) 13 | @component('klaravel::ui.dropdown', [ 14 | 'title' => $menuTitle, 15 | 'active' => is_array($menuItems) && array_key_exists($croute, $menuItems) 16 | ]) 17 | @foreach ($menuItems as $setUrl => $setLabel) 18 | {{ $setLabel }} 19 | @endforeach 20 | @endcomponent 21 | @else 22 | 27 | @endif 28 | @endforeach 29 | @endif 30 | @else 31 | @if (config('ksoft.show_integration_hints')) 32 | 33 | 38 | @endif 39 | @endif 40 | ``` 41 | -------------------------------------------------------------------------------- /wiki/trait-controllers.md: -------------------------------------------------------------------------------- 1 | # Controller traits 2 | 3 | ##### CanChangeStatuses 4 | 5 | On your controller 6 | 7 | ``` 8 | use Ksoft\Klaravel\Traits\CanChangeStatuses; 9 | // You must specify the field/s name and its changeable options 10 | protected $changeableStatus = [ 11 | 'active' => 'bool', // for booleans you can send 'true', 'on' ?? '1' 12 | 'status' => ['A','B','C'] // for enums, must exist in array. 13 | ]; 14 | ``` 15 | 16 | On your routes 17 | 18 | ``` 19 | Route::get('MODEL/change-status/{id}/{key}/{status}/', 'YOUR__Controller@changeStatus')->name('MODEL.status_change'); 20 | ``` 21 | 22 | On your blades, for example, a table column clickable icon: 23 | 24 | ``` 25 | 26 | 27 | 28 | 29 | 30 | ``` 31 | 32 | ##### CanUploadMedia 33 | 34 | This trait works with the Vue Component `klaravel-media-upload` and [laravel-media-library](https://docs.spatie.be/laravel-medialibrary/v7) 35 | 36 | ``` 37 | // Install library 38 | composer require spatie/laravel-medialibrary:^7.0.0 39 | // Publish migrations 40 | php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="migrations" 41 | // Migrate 42 | php artisan migrate 43 | // Optional, publish configuration 44 | php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="config" 45 | ``` 46 | 47 | Add Trait to controller 48 | 49 | ``` 50 | use Ksoft\Klaravel\Traits\CanUploadMedia; 51 | ``` 52 | 53 | Add the routes 54 | 55 | ``` 56 | Route::post('MODEL_PATH/{id}/media-upload', 'MODELController@upload')->name('MODEL_PATH.media.upload'); 57 | Route::get('MODEL_PATH/{id}/remove-media/{media?}', 'MODELController@remove')->name('MODEL_PATH.media.remove'); 58 | Route::get('MODEL_PATH/{id}/make-default-media/{media?}', 'MODELController@mediaDefault')->name('MODEL_PATH.media.makedefault'); 59 | ``` 60 | 61 | On your blade, using components. 62 | 63 | ``` 64 |
    65 |
    66 | 72 | 73 |
    74 |
    75 | @include('klaravel::ui.card-deck-media', [ 76 | 'medias' => $record->media, 77 | 'remove_url' => route_has($model_name.'.media.remove', $record), 78 | 'make_default_url' => route_has($model_name.'.media.makedefault', $record) 79 | ]) 80 |
    81 |
    82 | ``` 83 | -------------------------------------------------------------------------------- /wiki/trait-eloquent.md: -------------------------------------------------------------------------------- 1 | # Eloquent repository 2 | 3 | Quick reference for a manual implementation. 4 | 5 | #### Implementation 6 | 7 | Create an empty repository Class that extends from `EloquentRepo` 8 | 9 | ```php 10 | use Ksoft\Klaravel\Repositories\EloquentRepo; 11 | use App\Models\User; 12 | 13 | class UsersRepository extends EloquentRepo 14 | { 15 | public function model() 16 | { 17 | return User::class; 18 | } 19 | } 20 | ``` 21 | 22 | in your controller.. 23 | 24 | ```php 25 | use App\Repositories\UsersRepository; 26 | 27 | class ExampleController extends Controller 28 | { 29 | public function __construct(UsersRepository $repo) 30 | { 31 | $this->repo = $repo; 32 | } 33 | ``` 34 | 35 | you can do things like.. 36 | 37 | ```php 38 | $records = $this->repo->withPagination($request); 39 | $records = $this->repo->findWhere('slug', $request->slug_value); 40 | $record = $this->repo->findWhereFirst('slug', $request->slug_value); 41 | ``` 42 | 43 | #### available methods 44 | 45 | ```php 46 | public function all(); 47 | public function find($id); 48 | public function findWhere($column, $value); 49 | public function findWhereFirst($column, $value); 50 | public function findWhereLike($column, $value); 51 | public function paginateIf($records, $per_page = 0); 52 | public function create(array $properties); 53 | public function update($id, array $properties); 54 | public function delete($id); 55 | ``` 56 | -------------------------------------------------------------------------------- /wiki/trait-models.md: -------------------------------------------------------------------------------- 1 | # Models traits 2 | 3 | ##### ActiveScope 4 | 5 | This trait works for easy filtering of eloquent calls. Import following trait in your model: 6 | 7 | ``` 8 | use Ksoft\Klaravel\Traits\ActiveScope; 9 | ``` 10 | 11 | You will be able to do things like: 12 | 13 | ``` 14 | $records = Post::active()->get(); // defaults to 'active' name of attribute 15 | $records = Post::active('published')->get(); // specify the name. 16 | $records = Post::active(['published','active'])->get(); // get active *AND* published records. 17 | ``` 18 | 19 | and.. 20 | 21 | ``` 22 | $records = Post::notActive()->get(); 23 | ``` 24 | 25 | ##### HasLogs 26 | 27 | Enable logs on your models, more info on [laravel-activitylog](https://docs.spatie.be/laravel-activitylog/v2/introduction) 28 | 29 | ``` 30 | use Ksoft\Klaravel\Traits\HasLogs; 31 | ``` 32 | 33 | ``` 34 | activity('default') 35 | ->performedOn($anEloquentModel) 36 | ->causedBy($user) 37 | ->withProperties(['customProperty' => 'customValue']) 38 | ->log('Look mum, I logged something'); 39 | ``` 40 | 41 | 42 | ``` 43 | morphMany( 58 | ActivitylogServiceProvider::determineActivityModel(), 59 | 'subject' 60 | )->orderBy('id', 'DESC'); 61 | } 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /wiki/trait-repositories.md: -------------------------------------------------------------------------------- 1 | # QueryFiltersTrait 2 | 3 | Extend eloquent queries of your repository, helps you search more in less time by defining some 4 | groups of arrays. 5 | 6 | Include the Trait in your repository 7 | 8 | ``` 9 | use Ksoft\Klaravel\Traits\QueryFiltersTrait; 10 | ``` 11 | 12 | Declare the `$this->query` on your class and couple arrays to be the searchable fields. You should group 13 | them by field type, for example strings and booleans. 14 | 15 | ``` 16 | ... 17 | $this->query = ''; 18 | $this->attrsFilter = [ 19 | 'name', 'text', 'description', // as per your needs-... 20 | ]; 21 | ... 22 | ``` 23 | 24 | Now, on the method you are recieving the request, you could make a setup like this: 25 | 26 | ``` 27 | public function withPagination($perPage, $request) 28 | { 29 | $this->prepareQueryOrder($request); 30 | 31 | // Date range filter 32 | $this->applyDateRangeFilter($request, $field = 'dateRange', $attr = 'created_at'); // dateRange=[2012-12-1,2013-01-23] 33 | // or 34 | $this->applyDateSessionFilter($request, $attr = 'created_at'); 35 | 36 | // String filters LIKE %{{keyword}}% 37 | $this->applyTiposFilters($request); 38 | $this->applySingleAttrsFilters($request); // fields to search declared in $this->attrsFilter 39 | // Same as before but you can find coincidences in multiple fields, 40 | $this->applyEqualTypeFilter($request, $itemsArray, $multiple = true); 41 | // boleans 42 | foreach (['active','published'] as $attr){ 43 | $this->filterBool($attr, $value); // posibles $values: 0, 1 (and hardcoded) 'NULL', 'NOT_NULL' 44 | } 45 | 46 | return $this->query->paginate($perPage); 47 | } 48 | ``` 49 | 50 | Filter records from request, adjust to your convenience. 51 | 52 | ``` 53 | public function prepareQueryOrder($request) 54 | { 55 | $savedOrder = session('order', 'newest'); 56 | 57 | switch ($savedOrder) { 58 | case 'price_asc': 59 | $this->query = $this->model::orderBy('price', 'asc'); 60 | break; 61 | case 'price_desc': 62 | $this->query = $this->model::orderBy('price', 'desc'); 63 | break; 64 | default: 65 | $this->query = $this->model::orderBy('id', 'desc'); 66 | break; 67 | } 68 | } 69 | ``` 70 | -------------------------------------------------------------------------------- /wiki/trait-responses.md: -------------------------------------------------------------------------------- 1 | # Responses traits 2 | 3 | This two traits are meant to be using deppening on your respones, but the LumenResponsesTrait should work fine 4 | for boths: Laravel and Lumen. 5 | 6 | ``` 7 | use Ksoft\Klaravel\Traits\JsonTrait; 8 | use Ksoft\Klaravel\Traits\LumenResponsesTrait; 9 | ``` 10 | 11 | for use in your controllers 12 | 13 | ``` 14 | class BaseKrudController extends Controller 15 | { 16 | use LumenResponsesTrait, KrudControllerTrait; 17 | ``` 18 | --------------------------------------------------------------------------------