diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3f616b..15f6b93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: echo "TIMESTAMP_START=$(date +'%s')" >> $GITHUB_OUTPUT - name: "Slack notification: IN PROGRESS" id: slack - uses: slackapi/slack-github-action@v1.24.0 + uses: slackapi/slack-github-action@v1.25.0 with: channel-id: 'C068A06PV43' payload: | @@ -133,7 +133,7 @@ jobs: echo "DATE_END=$(date +'%Y-%m-%d %H:%M:%S')" >> $GITHUB_OUTPUT echo "DURATION_PHRASE=$(($(date +'%s')-$TIMESTAMP_START)) seconds" >> $GITHUB_OUTPUT - name: "Slack notification: Done" - uses: slackapi/slack-github-action@v1.24.0 + uses: slackapi/slack-github-action@v1.25.0 with: channel-id: 'C068A06PV43' update-ts: ${{ steps.slack.outputs.ts }} @@ -194,7 +194,7 @@ jobs: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - name: "Send a notification for failures" if: ${{ failure() }} - uses: slackapi/slack-github-action@v1.24.0 + uses: slackapi/slack-github-action@v1.25.0 with: channel-id: 'C068A06PV43' update-ts: ${{ steps.slack.outputs.ts }} diff --git a/README.md b/README.md index 50ed341..25e125a 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,9 @@ By default, the following libraries are loaded. - `favicon`: `/favicon.ico` - [Nunito](https://fonts.google.com/specimen/Nunito): Loaded from Google Fonts. -- [Bootstrap: 5.3.2](https://getbootstrap.com/docs/5.3/) -- [FontAwesome: 6.4.2](https://fontawesome.com/search?o=r&m=free) +- [Bootstrap: v5.3.3](https://getbootstrap.com/docs/5.3/) +- [FontAwesome: v6.5.1](https://fontawesome.com/search?o=r&m=free) +- [CKEditor 5: v41.1.0](https://github.com/ckeditor/ckeditor5) - [Vue 3 - https://unpkg.com/vue@3](https://vuejs.org/) - `/vendor/playground-blade.js` A small library to be loaded for Blade UI usage. Needs to be published. diff --git a/composer.json b/composer.json index ee8cfa8..ab83743 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,6 @@ "gammamatrix", "laravel", "playground", - "playground", "playground-blade" ], "homepage": "https://github.com/gammamatrix/playground-blade/wiki", @@ -20,11 +19,11 @@ ], "require": { "php": "^8.1", - "gammamatrix/playground": "dev-develop|dev-master|^73.0" + "gammamatrix/playground": "dev-develop|dev-master|dev-feature/*|^73.0" }, "require-dev": { - "gammamatrix/playground-auth": "dev-develop|dev-master|^73.0", - "gammamatrix/playground-test": "dev-develop|dev-master|^73.0", + "gammamatrix/playground-auth": "dev-develop|dev-master|dev-feature/*|^73.0", + "gammamatrix/playground-test": "dev-develop|dev-master|dev-feature/*|^73.0", "tomasvotruba/bladestan": "^0.4.1" }, "minimum-stability": "dev", diff --git a/config/playground-blade.php b/config/playground-blade.php index 1fc28ac..efbe60b 100644 --- a/config/playground-blade.php +++ b/config/playground-blade.php @@ -13,73 +13,192 @@ 'themes' => [ 'default' => [ 'bsTheme' => '', - 'editor' => '', + // 'editor' => '', 'enable' => (bool) env('PLAYGROUND_BLADE_THEME_DEFAULT_ENABLE', true), 'label' => 'Default Theme', 'key' => 'default', - 'icon' => '', + 'icon' => 'fa-solid fa-square', 'provider' => 'bootstrap', 'session' => true, + 'head' => [ + 'comment' => [ + 'asset' => 'comment', + 'comment' => 'head: using the default theme', + ], + // 'bootstrap-root' => [ + // 'rel' => 'stylesheet', + // 'asset' => 'stylesheet', + // 'href' => '/vendor/bootstrap-root-0001.css', + // 'version' => '5.3.3', + // 'always' => true, + // ], + 'anta' => [ + 'asset' => 'font', + 'href' => 'https://fonts.googleapis.com/css2?family=Anta&display=swap', + 'rel' => 'stylesheet', + 'always' => true, + ], + 'font-headers' => [ + 'asset' => 'style', + 'style' => 'h1, h2, h3, h4, h5, h6 {font-family: Anta, sans-serif;}', + 'always' => true, + ], + ], + 'body' => [ + 'comment' => [ + 'asset' => 'comment', + 'comment' => 'body: using the default theme', + ], + ], + ], + 'blue' => [ + 'bsTheme' => 'blue', + // 'editor' => '', + 'enable' => (bool) env('PLAYGROUND_BLADE_THEME_DEFAULT_ENABLE', true), + 'label' => 'Blue Theme', + 'key' => 'blue', + 'icon' => 'fa-solid fa-circle', + 'provider' => 'bootstrap', + 'session' => true, + 'head' => [ + 'comment' => [ + 'asset' => 'comment', + 'comment' => 'head: using the blue theme', + ], + 'bootstrap-root' => [ + 'rel' => 'stylesheet', + 'asset' => 'stylesheet', + 'href' => '/vendor/bootstrap-root-blue.css', + 'version' => '5.3.3', + 'always' => true, + ], + 'anta' => [ + 'asset' => 'font', + 'href' => 'https://fonts.googleapis.com/css2?family=Lobster&display=swap', + 'rel' => 'stylesheet', + 'always' => true, + ], + 'font-headers' => [ + 'asset' => 'style', + 'style' => 'h1, h2, h3, h4, h5, h6 {font-family: Lobster, sans-serif;}', + 'always' => true, + ], + ], + 'body' => [ + 'comment' => [ + 'asset' => 'comment', + 'comment' => 'body: using the default theme', + ], + ], ], 'dark' => [ 'bsTheme' => 'dark', - 'editor' => '/vendor/ckeditor-dark.css', + // 'editor' => '/vendor/ckeditor-dark.css', 'enable' => (bool) env('PLAYGROUND_BLADE_THEME_DARK_ENABLE', true), 'label' => 'Dark Theme', 'key' => 'dark', 'icon' => 'fa-solid fa-moon', 'provider' => 'bootstrap', 'session' => true, + 'head' => [ + 'ckeditor-dark' => [ + 'rel' => 'stylesheet', + 'asset' => 'stylesheet', + 'href' => '/vendor/ckeditor-dark.css', + 'version' => '41.1.0', + 'always' => true, + ], + ], ], 'light' => [ 'bsTheme' => 'light', - 'editor' => '/vendor/ckeditor-light.css', 'enable' => (bool) env('PLAYGROUND_BLADE_THEME_LIGHT_ENABLE', true), 'label' => 'Light Theme', 'key' => 'light', 'icon' => 'fa-solid fa-sun', 'provider' => 'bootstrap', 'session' => true, + 'head' => [ + 'ckeditor-light' => [ + 'rel' => 'stylesheet', + 'asset' => 'stylesheet', + 'href' => '/vendor/ckeditor-light.css', + 'version' => '41.1.0', + 'always' => true, + ], + ], ], 'bootstrap-dark' => [ 'bsTheme' => 'dark', - 'editor' => '/vendor/ckeditor-bootstrap.css', 'enable' => false, - 'label' => 'CkEditor Unified Bootstrap Theme under Dark', + 'label' => 'CKEditor Unified Bootstrap Theme under Dark', 'key' => 'bootstrap-dark', 'icon' => 'fa-brands fa-bootstrap', 'provider' => 'bootstrap', 'session' => true, + 'head' => [ + 'ckeditor-light' => [ + 'rel' => 'stylesheet', + 'asset' => 'stylesheet', + 'href' => '/vendor/ckeditor-bootstrap.css', + 'version' => '41.1.0', + 'always' => true, + ], + ], ], 'bootstrap-light' => [ 'bsTheme' => 'light', - 'editor' => '/vendor/ckeditor-bootstrap.css', 'enable' => false, - 'label' => 'CkEditor Unified Bootstrap Theme under Light', + 'label' => 'CKEditor Unified Bootstrap Theme under Light', 'key' => 'bootstrap-light', 'icon' => 'fa-brands fa-bootstrap', 'provider' => 'bootstrap', 'session' => true, + 'head' => [ + 'ckeditor-light' => [ + 'rel' => 'stylesheet', + 'asset' => 'stylesheet', + 'href' => '/vendor/ckeditor-bootstrap.css', + 'version' => '41.1.0', + 'always' => true, + ], + ], ], 'lark-dark' => [ 'bsTheme' => 'dark', - 'editor' => '/vendor/ckeditor-lark.css', 'enable' => false, - 'label' => 'CkEditor Lark Theme under Dark', + 'label' => 'CKEditor Lark Theme under Dark', 'key' => 'lark-dark', 'icon' => 'fa-solid fa-dove fa-moon', 'provider' => 'bootstrap', 'session' => true, + 'head' => [ + 'ckeditor-light' => [ + 'rel' => 'stylesheet', + 'asset' => 'stylesheet', + 'href' => '/vendor/ckeditor-lark.css', + 'version' => '41.1.0', + 'always' => true, + ], + ], ], 'lark-light' => [ 'bsTheme' => 'light', - 'editor' => '/vendor/ckeditor-lark.css', 'enable' => false, - 'label' => 'CkEditor Lark Theme under Light', + 'label' => 'CKEditor Lark Theme under Light', 'key' => 'lark-light', 'icon' => 'fa-solid fa-dove fa-sun', 'provider' => 'bootstrap', 'session' => true, + 'head' => [ + 'ckeditor-light' => [ + 'rel' => 'stylesheet', + 'asset' => 'stylesheet', + 'href' => '/vendor/ckeditor-lark.css', + 'version' => '41.1.0', + 'always' => true, + ], + ], ], ], /* @@ -103,12 +222,15 @@ 'rel' => 'icon', 'always' => true, ], - // 'gstatic' => [ - // 'asset' => 'font', - // 'version' => '', - // 'integrity' => '', - // 'href' => 'https://fonts.gstatic.com/', - // ], + 'preconnect-googleapis' => [ + 'asset' => 'link', + 'href' => 'https://fonts.googleapis.com/', + ], + 'preconnect-gstatic' => [ + 'asset' => 'link', + 'crossorigin' => '', + 'href' => 'https://fonts.gstatic.com/', + ], 'nunito' => [ 'asset' => 'font', 'href' => 'https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap', @@ -119,25 +241,30 @@ 'asset' => 'script', 'crossorigin' => 'anonymous', 'integrity' => '', - 'src' => 'https://cdn.ckeditor.com/ckeditor5/34.2.0/classic/ckeditor.js', - 'version' => '34.2.0', + 'src' => 'https://cdn.ckeditor.com/ckeditor5/41.1.0/classic/ckeditor.js', + 'version' => '41.1.0', + ], + 'ckeditor-style' => [ + 'asset' => 'style', + 'style' => '.ck-editor__editable_inline, .editor__editable {min-height: 200px;}', + 'version' => '41.1.0', ], 'bootstrap-css' => [ 'rel' => 'stylesheet', 'asset' => 'stylesheet', 'crossorigin' => 'anonymous', - 'integrity' => 'sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN', - 'href' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css', - 'version' => '5.3.2', + 'integrity' => 'sha512-jnSuA4Ss2PkkikSOLtYs8BlYIeeIK1h99ty4YfvRPAlzr377vr3CXDb7sb7eEEBYjDtcYj+AjBH3FLv5uSJuXg==', + 'href' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css', + 'version' => '5.3.3', 'always' => true, ], 'fontawesome-css' => [ 'rel' => 'stylesheet', 'asset' => 'font', 'crossorigin' => 'anonymous', - 'integrity' => 'sha512-z3gLpd7yknf1YoNbCzqRKc4qyor8gaKU1qmn+CShxbuBusANI9QpRohGBreCFkKxLhei6S9CQXFEbbKuqLg0DA==', - 'href' => 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css', - 'version' => '6.4.2', + 'integrity' => 'sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==', + 'href' => 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css', + 'version' => '6.5.1', 'always' => true, ], 'vue' => [ @@ -148,7 +275,7 @@ 'version' => '', 'always' => true, ], - 'body-nunito' => [ + 'font-body' => [ 'asset' => 'style', 'style' => 'body {font-family: Nunito, sans-serif;}', 'always' => true, @@ -158,9 +285,9 @@ 'bootstrap' => [ 'asset' => 'script', 'crossorigin' => 'anonymous', - 'integrity' => 'sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL', - 'src' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js', - 'version' => '5.3.2', + 'integrity' => 'sha512-7Pi/otdlbbCR+LnW+F7PwFcSDJOuUJB3OxtEHbg4vSMvzvJjde4Po1v4BR9Gdc9aXNUNFVUY+SK51wWT8WF0Gg==', + 'src' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js', + 'version' => '5.3.3', 'always' => true, ], 'playground-blade' => [ @@ -184,9 +311,9 @@ 'asset' => 'script', 'referrerpolicy' => 'no-referrer', 'crossorigin' => 'anonymous', - 'integrity' => 'sha512-uKQ39gEGiyUJl4AI6L+ekBdGKpGw4xJ55+xyJG7YFlJokPNYegn9KwQ3P8A7aFQAUtUsAQHep+d/lrGqrbPIDQ==', - 'src' => 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/js/all.min.js', - 'version' => '6.4.2', + 'integrity' => 'sha512-GWzVrcGlo0TxTRvz9ttioyYJ+Wwk9Ck0G81D+eO63BaqHaJ3YZX9wuqjwgfcV/MrB2PhaVX9DkYVhbFpStnqpQ==', + 'src' => 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/js/all.min.js', + 'version' => '6.5.1', 'always' => true, ], ], diff --git a/resources/views/components/table/data-row-actions-delete-relationship.blade.php b/resources/views/components/table/data-row-actions-delete-relationship.blade.php new file mode 100644 index 0000000..42d0b70 --- /dev/null +++ b/resources/views/components/table/data-row-actions-delete-relationship.blade.php @@ -0,0 +1,12 @@ +
+ @method('DELETE') + @csrf + + + + +
diff --git a/resources/views/components/table/data-row-actions-delete.blade.php b/resources/views/components/table/data-row-actions-delete.blade.php new file mode 100644 index 0000000..c684301 --- /dev/null +++ b/resources/views/components/table/data-row-actions-delete.blade.php @@ -0,0 +1,10 @@ +
+ @method('DELETE') + @csrf + + +
diff --git a/resources/views/components/table/data-row-actions-edit.blade.php b/resources/views/components/table/data-row-actions-edit.blade.php new file mode 100644 index 0000000..5401561 --- /dev/null +++ b/resources/views/components/table/data-row-actions-edit.blade.php @@ -0,0 +1,19 @@ +@if (!empty($record['deleted_at']) && $routeRestore) +
+ @method('PUT') + @csrf + + +
+@elseif ($withEdit && $routeEdit) + + + Edit + +@endif diff --git a/resources/views/components/table/data-row-actions-unlock.blade.php b/resources/views/components/table/data-row-actions-unlock.blade.php new file mode 100644 index 0000000..b20a43a --- /dev/null +++ b/resources/views/components/table/data-row-actions-unlock.blade.php @@ -0,0 +1,10 @@ +
+ @method('DELETE') + @csrf + + +
diff --git a/resources/views/components/table/data-row-actions.blade.php b/resources/views/components/table/data-row-actions.blade.php index c62a898..ee3c4ff 100644 --- a/resources/views/components/table/data-row-actions.blade.php +++ b/resources/views/components/table/data-row-actions.blade.php @@ -1,57 +1,12 @@
- - @php - if (!empty($record['deleted_at'])) { - $withDelete = false; - } - @endphp - - @if ($withDelete && $routeDeleteRelationship && $routeDelete) -
- @method('DELETE') - @csrf - - - - -
- @elseif ($withDelete && $routeDelete) -
- @method('DELETE') - @csrf - - -
+ @if ($withUnlock && !empty($record['locked']) && $routeUnlock) + @include('playground::components/table/data-row-actions-unlock') + @else + @if ($withDelete && $routeDelete && empty($record['deleted_at'])) + @include('playground::components/table/data-row-actions-delete') + @endif + @include('playground::components/table/data-row-actions-edit') @endif - - @if (!empty($record['deleted_at']) && $routeRestore) -
- @method('PUT') - @csrf - - -
- @elseif ($withEdit && $routeEdit) - - - Edit - - @endif -
diff --git a/resources/views/components/table/data.blade.php b/resources/views/components/table/data.blade.php index 3bf95e1..01ceb69 100644 --- a/resources/views/components/table/data.blade.php +++ b/resources/views/components/table/data.blade.php @@ -33,6 +33,13 @@ 'roles' => ['admin', 'manager'], ])->allowed(); +$withUnlock = \Playground\Auth\Facades\Can::access($user, [ + 'allow' => false, + 'any' => true, + 'privilege' => $withPrivilege . ':unlock', + 'roles' => ['admin', 'manager'], +])->allowed(); + /** * @var array> $columns The columns in the table, keyed by slug. */ diff --git a/resources/views/layouts/bootstrap.blade.php b/resources/views/layouts/bootstrap.blade.php index e399e92..b062b9d 100644 --- a/resources/views/layouts/bootstrap.blade.php +++ b/resources/views/layouts/bootstrap.blade.php @@ -107,17 +107,13 @@ {{ !empty($appName) ? sprintf('%1$s: ', $appName) : '' }}@yield('title') - @foreach (Playground\Blade\Facades\Ui::headAssets() as $asset) + @foreach (Playground\Blade\Facades\Ui::headAssets($theme) as $asset) {!! $asset !!} @endforeach @stack('scripts') @yield('head') - @if (!empty($theme->editor())) - - @endif - @if (!$withBreadcrumbs) @endif - @@ -184,7 +174,7 @@ @stack('modals') @stack('body-last') - @foreach (Playground\Blade\Facades\Ui::bodyAssets() as $asset) + @foreach (Playground\Blade\Facades\Ui::bodyAssets($theme) as $asset) {!! $asset !!} @endforeach diff --git a/resources/views/layouts/resource/detail-information.blade.php b/resources/views/layouts/resource/detail-information.blade.php index 0ed935f..bf55649 100644 --- a/resources/views/layouts/resource/detail-information.blade.php +++ b/resources/views/layouts/resource/detail-information.blade.php @@ -20,87 +20,111 @@ {{ __('Edit') }} + @endif +

{{ $data->getAttributeValue($meta['info']['model_attribute']) }}

+ @if ($withImage && $data && $data->image) +
+ {{ $meta['info']['model_label'] }} Image +
@endif -

{{ $data->label }}

- -@if ($withImage && $data && $data->image) -
- {{ $meta['info']['model_label'] }} Image -
-@endif -
+
-

{{ __('Information') }}

+

{{ __('Information') }}

- - - - - - - @if ($parent) +
{{ __('Slug') }}{{ $data->slug }}
+ - + + + + @if ($parent) + + + + + @endif + + - @endif - - - - - - - - - - - - - @yield('detail-information-table') - -
{{ __('Parent ' . $meta['info']['model_label']) }}{{ __('Slug') }}{{ $data->slug }}
{{ __('Parent ' . $meta['info']['model_label']) }} + + {{ $parent->label }} + +
{{ __('Created') }} - - {{ $parent->label }} - + @if ($data->created_at) + + @endif
{{ __('Created') }} - @if ($data->created_at) - - @endif -
{{ __('Updated') }} - @if ($data->updated_at) - - @endif -
{{ __('Active') }} - @if ($data->active) - - @endif -
+ + {{ __('Updated') }} + + @if ($data->updated_at) + + @endif + + + @yield('detail-information-table') + + - @if ($data->description) -

{{ __('Description') }}

+ @if ($data->description) +

{{ __('Description') }}

-
{{ $data->description }}
- @endif +
{{ $data->description }}
+ @endif - @if ($data->introduction) -

{{ __('Introduction') }}

+ @if ($data->introduction) +

{{ __('Introduction') }}

-
{{ $data->introduction }}
- @endif +
{{ $data->introduction }}
+ @endif - @if ($data->content) -

{{ __('Content') }}

+ @if ($data->content) +

{{ __('Content') }}

-
{!! $data->content !!}
- @endif +
{!! $data->content !!}
+ @endif - @if ($data->summary) -

{{ __('Summary') }}

+ @if ($data->summary) +

{{ __('Summary') }}

-
{!! $data->summary !!}
- @endif +
{!! $data->summary !!}
+ @endif -
+
+ + + + + diff --git a/resources/views/layouts/resource/detail.blade.php b/resources/views/layouts/resource/detail.blade.php index c7c8389..0d9bb5d 100644 --- a/resources/views/layouts/resource/detail.blade.php +++ b/resources/views/layouts/resource/detail.blade.php @@ -28,6 +28,7 @@ $withPrivilege = !empty($meta['info']) && !empty($meta['info']['privilege']) && is_string($meta['info']['privilege']) ? $meta['info']['privilege'] : 'playground'; +$routeUnlock = !$data ? '' : route(sprintf('%1$s.unlock', $meta['info']['model_route']), [$meta['info']['model_slug'] => $data->getAttributeValue('id')]); $routeDelete = !$data ? '' : route(sprintf('%1$s.destroy', $meta['info']['model_route']), [$meta['info']['model_slug'] => $data->getAttributeValue('id')]); $routeEdit = !$data ? '' : route(sprintf('%1$s.edit', $meta['info']['model_route']), [$meta['info']['model_slug'] => $data->getAttributeValue('id')]); @@ -54,6 +55,13 @@ 'roles' => ['admin', 'manager'], ])->allowed(); +$withUnlock = \Playground\Auth\Facades\Can::access($user, [ + 'allow' => false, + 'any' => true, + 'privilege' => $withPrivilege . ':unlock', + 'roles' => ['admin', 'manager'], +])->allowed(); + /** * @var boolean|string $withInfo */ diff --git a/resources/views/layouts/resource/form-information.blade.php b/resources/views/layouts/resource/form-information.blade.php index 62788a4..cc6d83d 100644 --- a/resources/views/layouts/resource/form-information.blade.php +++ b/resources/views/layouts/resource/form-information.blade.php @@ -3,37 +3,30 @@ {{ __('Information') }} @if ($withFormLabel) - @formInput([ - 'label' => 'Label', - 'column' => 'label', - 'autocomplete' => false, - 'rules' => [ - 'required' => true, - 'maxlength' => 255, - ], - ]) + + + @endif + + @if ($withFormTitle) + + @endif @if ($withFormSlug) - @formInput([ - 'label' => 'SLUG', - 'column' => 'slug', - 'autocomplete' => false, - 'rules' => [ - 'required' => 'patch' === $_method, - 'maxlength' => 255, - ], - ]) + @endif - @if ($withFormParent) - @formSelect([ - 'label' => sprintf('%1$s Parent', $meta['info']['module_label']), - 'column' => 'parent_id', - 'default' => true, - 'key' => $meta['info']['model_attribute'], - 'records' => $parents, - ]) + @if ($withFormParent && !empty($parents)) + @endif @yield('fieldset-information') diff --git a/resources/views/layouts/resource/form-status.blade.php b/resources/views/layouts/resource/form-status.blade.php index 189d43d..3b9ec3f 100644 --- a/resources/views/layouts/resource/form-status.blade.php +++ b/resources/views/layouts/resource/form-status.blade.php @@ -9,24 +9,33 @@
- + {{ $data->active ? 'checked' : '' }}> +
- + {{ $data->locked ? 'checked' : '' }}> +
- + {{ $data->flagged ? 'checked' : '' }}> +
diff --git a/resources/views/layouts/resource/form.blade.php b/resources/views/layouts/resource/form.blade.php index 58db4c1..0e5fcae 100644 --- a/resources/views/layouts/resource/form.blade.php +++ b/resources/views/layouts/resource/form.blade.php @@ -29,6 +29,21 @@ */ $withFormLabel = isset($withFormLabel) && is_bool($withFormLabel) ? $withFormLabel : true; +/** + * @var boolean $withFormLabelRequired + */ +$withFormLabelRequired = $withFormLabel && !empty($withFormLabelRequired); + +/** + * @var boolean $withFormTitle + */ +$withFormTitle = isset($withFormTitle) && is_bool($withFormTitle) ? $withFormTitle : true; + +/** + * @var boolean $withFormTitleRequired + */ +$withFormTitleRequired = $withFormTitle && !empty($withFormTitleRequired); + /** * @var boolean $withFormSlug */ @@ -39,11 +54,6 @@ */ $withFormParent = isset($withFormParent) && is_bool($withFormParent) ? $withFormParent : true; -/** - * @var boolean $withFormSpec - */ -$withFormSpec = isset($withFormSpec) && is_bool($withFormSpec) ? $withFormSpec : true; - /** * @var boolean|string $withFormButtons */ diff --git a/resources/views/layouts/resource/index.blade.php b/resources/views/layouts/resource/index.blade.php index 21a9ac0..2d65b54 100644 --- a/resources/views/layouts/resource/index.blade.php +++ b/resources/views/layouts/resource/index.blade.php @@ -101,6 +101,7 @@ 'routeEdit' => sprintf('%1$s.edit', $meta['info']['model_route']), 'routeDelete' => sprintf('%1$s.destroy', $meta['info']['model_route']), 'routeRestore' => sprintf('%1$s.restore', $meta['info']['model_route']), + 'routeUnlock' => sprintf('%1$s.unlock', $meta['info']['model_route']), 'paginator' => $paginator ?? null, 'privilege' => $withPrivilege, 'styling' => [ @@ -152,7 +153,7 @@ + :route-unlock="$tableComponent['routeUnlock']" :styling="$tableComponent['styling']"> {{ $meta['info']['model_label_plural'] }} diff --git a/src/Assets/Comment.php b/src/Assets/Comment.php new file mode 100644 index 0000000..8515697 --- /dev/null +++ b/src/Assets/Comment.php @@ -0,0 +1,46 @@ +always = ! empty($options['always']); + + if (! empty($options['comment']) + && is_string($options['comment']) + ) { + $this->comment = $options['comment']; + } + + return $this; + } + + public function always(): bool + { + return $this->always; + } + + public function comment(): string + { + return $this->comment; + } + + public function __toString(): string + { + return sprintf('', $this->comment()); + // return sprintf('', e($this->commentq())); + } +} diff --git a/src/Assets/Contracts/Comment.php b/src/Assets/Contracts/Comment.php new file mode 100644 index 0000000..aaf201d --- /dev/null +++ b/src/Assets/Contracts/Comment.php @@ -0,0 +1,15 @@ +initAssets) { - return $this; - } - - $config = config('playground-blade'); - - if (is_array($config)) { - if (! empty($config['assets']) && is_array($config['assets'])) { - if (! empty($config['assets']['head']) && is_array($config['assets']['head'])) { - $this->loadHeadAssets($config['assets']['head']); - } - if (! empty($config['assets']['body']) && is_array($config['assets']['body'])) { - $this->loadBodyAssets($config['assets']['body']); - } - } - } - - $this->initAssets = true; - - return $this; - } - /** * @param array $assets */ public function loadBodyAssets(array $assets = []): self { $allowed = [ + 'comment', 'script', 'style', 'link', @@ -75,6 +53,8 @@ public function loadBodyAssets(array $assets = []): self $asset = new Assets\Style($meta); } elseif ($type === 'link') { $asset = new Assets\Link($meta); + } elseif ($type === 'comment') { + $asset = new Assets\Comment($meta); } if ($asset) { $this->bodyAssets[$key] = $asset; @@ -91,6 +71,7 @@ public function loadBodyAssets(array $assets = []): self public function loadHeadAssets(array $assets = []): self { $allowed = [ + 'comment', 'font', 'icon', 'link', @@ -122,6 +103,8 @@ public function loadHeadAssets(array $assets = []): self $asset = new Assets\Style($meta); } elseif ($type === 'stylesheet') { $asset = new Assets\Stylesheet($meta); + } elseif ($type === 'comment') { + $asset = new Assets\Comment($meta); } if ($asset) { @@ -136,16 +119,30 @@ public function loadHeadAssets(array $assets = []): self /** * @return array */ - public function bodyAssets(): array + public function bodyAssets(Theme $theme = null): array { - return $this->initAssets()->bodyAssets; + if (! $theme) { + return $this->initAssets()->bodyAssets; + } + + return array_replace( + $this->initAssets()->bodyAssets, + $theme->bodyAssets() + ); } /** * @return array */ - public function headAssets(): array + public function headAssets(Theme $theme = null): array { - return $this->initAssets()->headAssets; + if (! $theme) { + return $this->initAssets()->headAssets; + } + + return array_replace( + $this->initAssets()->headAssets, + $theme->headAssets() + ); } } diff --git a/src/Themes/Bootstrap.php b/src/Themes/Bootstrap.php index 8ff4148..ba01395 100644 --- a/src/Themes/Bootstrap.php +++ b/src/Themes/Bootstrap.php @@ -8,8 +8,6 @@ /** * \Playground\Blade\Themed\Bootstrap - * - * @method string editor() */ class Bootstrap extends Theme implements BootstrapContract { diff --git a/src/Themes/Theme.php b/src/Themes/Theme.php index 317ffd7..f1cc1f5 100644 --- a/src/Themes/Theme.php +++ b/src/Themes/Theme.php @@ -4,19 +4,22 @@ */ namespace Playground\Blade\Themes; +use Playground\Blade\Concerns\WithAssets; +use Playground\Blade\Contracts\HasAssets; + /** - * \Playground\Blade\Ui\Theme + * Playground\Blade\Themes\Theme */ -class Theme +class Theme implements HasAssets { + use WithAssets; + protected bool $enable = false; protected string $key = ''; protected string $label = ''; - protected string $editor = ''; - protected string $icon = ''; protected string $provider = ''; @@ -36,6 +39,17 @@ public function __construct( // $this->sessionThemeName = $sessionThemeName; } + public function initAssets(): self + { + if ($this->initAssets) { + return $this; + } + + $this->initAssets = true; + + return $this; + } + /** * @param array $options */ @@ -62,18 +76,31 @@ public function setOptions(array $options = []): self $this->label = $options['label']; } - if (! empty($options['editor']) - && is_string($options['editor']) + if (! empty($options['provider']) + && is_string($options['provider']) ) { - $this->editor = $options['editor']; + $this->provider = $options['provider']; } - if (! empty($options['editor']) - && is_string($options['editor']) + if (! empty($options['body']) + && is_array($options['body']) ) { - $this->editor = $options['editor']; + $this->loadBodyAssets($options['body']); } + if (! empty($options['head']) + && is_array($options['head']) + ) { + $this->loadHeadAssets($options['head']); + } + + $this->initAssets(); + // dd([ + // '__METHOD__' => __METHOD__, + // '$options' => $options, + // '$this' => $this, + // ]); + return $this; } @@ -87,9 +114,9 @@ public function key(): string return $this->key; } - public function editor(): string + public function provider(): string { - return $this->editor; + return $this->provider; } public function label(): string diff --git a/src/Ui.php b/src/Ui.php index 24e60b9..d19bbcf 100644 --- a/src/Ui.php +++ b/src/Ui.php @@ -16,4 +16,28 @@ class Ui implements HasAssets, HasThemes { use WithAssets; use WithThemes; + + public function initAssets(): self + { + if ($this->initAssets) { + return $this; + } + + $config = config('playground-blade'); + + if (is_array($config)) { + if (! empty($config['assets']) && is_array($config['assets'])) { + if (! empty($config['assets']['head']) && is_array($config['assets']['head'])) { + $this->loadHeadAssets($config['assets']['head']); + } + if (! empty($config['assets']['body']) && is_array($config['assets']['body'])) { + $this->loadBodyAssets($config['assets']['body']); + } + } + } + + $this->initAssets = true; + + return $this; + } } diff --git a/src/View/Components/Table/Data.php b/src/View/Components/Table/Data.php index fead2bd..3a5649f 100644 --- a/src/View/Components/Table/Data.php +++ b/src/View/Components/Table/Data.php @@ -27,6 +27,7 @@ public function __construct( public string $routeParameterKey = 'id', public string $routeEdit = '', public string $routeRestore = '', + public string $routeUnlock = '', public string $routeDelete = '', public string $routeDeleteRelationship = '', public string $routeDeleteRelationshipId = '',