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());
+ }
+}