diff --git a/panel/src/components/Forms/Field/SectionField.vue b/panel/src/components/Forms/Field/SectionField.vue new file mode 100644 index 0000000000..0b872d79b2 --- /dev/null +++ b/panel/src/components/Forms/Field/SectionField.vue @@ -0,0 +1,23 @@ + + + diff --git a/panel/src/components/Forms/Field/index.js b/panel/src/components/Forms/Field/index.js index 73761adaa9..c2fd2b7be4 100644 --- a/panel/src/components/Forms/Field/index.js +++ b/panel/src/components/Forms/Field/index.js @@ -20,6 +20,7 @@ import PagePickerField from "./PagePickerField.vue"; import PasswordField from "./PasswordField.vue"; import RadioField from "./RadioField.vue"; import RangeField from "./RangeField.vue"; +import SectionField from "./SectionField.vue"; import SelectField from "./SelectField.vue"; import SlugField from "./SlugField.vue"; import StatsField from "./StatsField.vue"; @@ -65,6 +66,7 @@ export default { app.component("k-password-field", PasswordField); app.component("k-radio-field", RadioField); app.component("k-range-field", RangeField); + app.component("k-section-field", SectionField); app.component("k-select-field", SelectField); app.component("k-slug-field", SlugField); app.component("k-stats-field", StatsField); diff --git a/panel/src/components/Forms/ModelForm.vue b/panel/src/components/Forms/ModelForm.vue new file mode 100644 index 0000000000..dd0d1634b1 --- /dev/null +++ b/panel/src/components/Forms/ModelForm.vue @@ -0,0 +1,57 @@ + + + diff --git a/panel/src/components/Forms/index.js b/panel/src/components/Forms/index.js index f83d5e8965..0a4c6873e6 100644 --- a/panel/src/components/Forms/index.js +++ b/panel/src/components/Forms/index.js @@ -5,6 +5,7 @@ import Fieldset from "./Fieldset.vue"; import Form from "./Form.vue"; import FormControls from "./FormControls.vue"; import Input from "./Input.vue"; +import ModelForm from "./ModelForm.vue"; /* Form parts */ import Blocks from "./Blocks/index.js"; @@ -22,6 +23,7 @@ export default { app.component("k-form", Form); app.component("k-form-controls", FormControls); app.component("k-input", Input); + app.component("k-model-form", ModelForm); app.use(Blocks); app.use(Inputs); diff --git a/panel/src/components/Views/Files/FileView.vue b/panel/src/components/Views/Files/FileView.vue index eb7b38f51d..9378319a97 100644 --- a/panel/src/components/Views/Files/FileView.vue +++ b/panel/src/components/Views/Files/FileView.vue @@ -43,17 +43,12 @@ - diff --git a/panel/src/components/Views/Pages/PageView.vue b/panel/src/components/Views/Pages/PageView.vue index 1ab4c358c5..880466f087 100644 --- a/panel/src/components/Views/Pages/PageView.vue +++ b/panel/src/components/Views/Pages/PageView.vue @@ -36,17 +36,12 @@ - diff --git a/panel/src/components/Views/Pages/SiteView.vue b/panel/src/components/Views/Pages/SiteView.vue index a696042ce9..4f3013ccfa 100644 --- a/panel/src/components/Views/Pages/SiteView.vue +++ b/panel/src/components/Views/Pages/SiteView.vue @@ -40,13 +40,12 @@ - diff --git a/panel/src/components/Views/Preview/PreviewForm.vue b/panel/src/components/Views/Preview/PreviewForm.vue index 317df07321..a1b05ab5c5 100644 --- a/panel/src/components/Views/Preview/PreviewForm.vue +++ b/panel/src/components/Views/Preview/PreviewForm.vue @@ -21,8 +21,9 @@
- diff --git a/panel/src/components/Views/Users/UserView.vue b/panel/src/components/Views/Users/UserView.vue index 50a3893833..57f5f5eea4 100644 --- a/panel/src/components/Views/Users/UserView.vue +++ b/panel/src/components/Views/Users/UserView.vue @@ -57,17 +57,12 @@ - diff --git a/src/Blueprint/Blueprint.php b/src/Blueprint/Blueprint.php index 54492447f2..f75fa14d47 100644 --- a/src/Blueprint/Blueprint.php +++ b/src/Blueprint/Blueprint.php @@ -10,6 +10,7 @@ use Kirby\Exception\NotFoundException; use Kirby\Filesystem\F; use Kirby\Form\Field; +use Kirby\Form\Field\SectionField; use Kirby\Toolkit\A; use Kirby\Toolkit\I18n; use Kirby\Toolkit\Str; @@ -819,7 +820,7 @@ protected function resolveFieldReferences(array $fields): array public function section(string $name): Section|null { if (empty($this->sections[$name]) === true) { - return null; + return $this->sectionFromField($name); } if ($this->sections[$name] instanceof Section) { @@ -836,6 +837,24 @@ public function section(string $name): Section|null return $this->sections[$name] = new Section($props['type'], $props); } + protected function sectionFromField(string $name): Section|null + { + if ($fieldProps = $this->field($name)) { + if ($fieldProps['type'] !== 'section') { + return null; + } + + unset($fieldProps['type']); + + $field = new SectionField(...$fieldProps); + $field->setModel($this->model()); + + return $field->section(); + } + + return null; + } + /** * Returns all sections */ diff --git a/src/Cms/Core.php b/src/Cms/Core.php index 21267bc3f4..e022b41c3e 100644 --- a/src/Cms/Core.php +++ b/src/Cms/Core.php @@ -32,6 +32,7 @@ use Kirby\Form\Field\PasswordField; use Kirby\Form\Field\RadioField; use Kirby\Form\Field\RangeField; +use Kirby\Form\Field\SectionField; use Kirby\Form\Field\SelectField; use Kirby\Form\Field\SlugField; use Kirby\Form\Field\StatsField; @@ -272,6 +273,7 @@ public function fields(): array 'password' => PasswordField::class, 'radio' => RadioField::class, 'range' => RangeField::class, + 'section' => SectionField::class, 'select' => SelectField::class, 'slug' => SlugField::class, 'stats' => StatsField::class, diff --git a/src/Form/Field/SectionField.php b/src/Form/Field/SectionField.php new file mode 100644 index 0000000000..21a9537eb8 --- /dev/null +++ b/src/Form/Field/SectionField.php @@ -0,0 +1,44 @@ +props = $props; + $this->section = $section; + } + + public function props(): array + { + return [ + ...parent::props(), + 'sectionType' => $this->section, + ]; + } + + public function section(): Section + { + return new Section($this->section, [ + 'model' => $this->model(), + ...$this->props + ]); + } +} diff --git a/src/Panel/Controller/View/ModelViewController.php b/src/Panel/Controller/View/ModelViewController.php index b4a0c98bb4..67e5c1e57f 100644 --- a/src/Panel/Controller/View/ModelViewController.php +++ b/src/Panel/Controller/View/ModelViewController.php @@ -4,6 +4,7 @@ use Kirby\Cms\Language; use Kirby\Cms\ModelWithContent; +use Kirby\Form\Field\SectionField; use Kirby\Form\Fields; use Kirby\Http\Uri; use Kirby\Panel\Controller\ViewController; @@ -23,6 +24,7 @@ */ abstract class ModelViewController extends ViewController { + protected Fields $fields; protected Model $panel; public function __construct( @@ -47,6 +49,11 @@ public function component(): string return 'k-' . ($this->model::CLASS_ALIAS ?? 'model') . '-view'; } + public function fields(): Fields + { + return $this->fields ??= Fields::for($this->model, 'current'); + } + public function load(): View { return new View(...$this->props()); @@ -131,6 +138,43 @@ public function tab(): array|null $tab = $this->request->get('tab'); $tab = $this->model->blueprint()->tab($tab); $tab ??= $this->tabs()[0] ?? null; + + if ($tab === null) { + return $tab; + } + + return $this->tabSimplified($tab); + } + + protected function tabSimplified(array $tab): array + { + $form = $this->fields(); + + foreach ($tab['columns'] as $columnIndex => $column) { + $fields = []; + + foreach ($column['sections'] as $sectionIndex => $section) { + if ($section['type'] === 'fields') { + foreach ($section['fields'] as $name => $field) { + if ($formField = $form->get($name)) { + $fields[$formField->name()] = $formField->props(); + } + } + } else { + $field = new SectionField($section['type'], ...$section); + $field->setModel($this->model()); + + $fields[$sectionIndex] = $field->props(); + } + } + + $column['fields'] = $fields; + + unset($column['sections']); + + $tab['columns'][$columnIndex] = $column; + } + return $tab; } @@ -153,7 +197,7 @@ abstract public function title(): string; public function versions(): array { $language = Language::ensure('current'); - $fields = Fields::for($this->model, $language); + $fields = $this->fields(); $latestVersion = $this->model->version('latest'); $changesVersion = $this->model->version('changes'); diff --git a/tests/Blueprint/BlueprintTest.php b/tests/Blueprint/BlueprintTest.php index f73f1913b9..3687a7b544 100644 --- a/tests/Blueprint/BlueprintTest.php +++ b/tests/Blueprint/BlueprintTest.php @@ -532,6 +532,22 @@ public function testSectionTypeFromName(): void $this->assertSame('info', $blueprint->sections()['info']->type()); } + public function testSectionFromField(): void + { + // with options + $blueprint = new Blueprint([ + 'model' => $this->model, + 'fields' => [ + 'info' => [ + 'type' => 'section', + 'section' => 'info' + ] + ] + ]); + + $this->assertSame('info', $blueprint->section('info')->type()); + } + public function testPreset(): void { $blueprint = new Blueprint([ diff --git a/tests/Form/Field/SectionFieldTest.php b/tests/Form/Field/SectionFieldTest.php new file mode 100644 index 0000000000..6b5aad440a --- /dev/null +++ b/tests/Form/Field/SectionFieldTest.php @@ -0,0 +1,42 @@ +field('section', [ + 'section' => 'pages' + ]); + + $props = $field->props(); + + ksort($props); + + $expected = [ + 'hidden' => false, + 'name' => 'section', + 'saveable' => false, + 'sectionType' => 'pages', + 'type' => 'section', + 'when' => null, + 'width' => '1/1' + ]; + + $this->assertSame($expected, $props); + } + + public function testSection(): void + { + $field = $this->field('section', [ + 'section' => 'pages' + ]); + + $this->assertInstanceOf(Section::class, $field->section()); + } +}