Skip to content

Commit 3f0f199

Browse files
authored
Move Layout Builder to Core (#2223)
This PR addresses #1921 It adds a new Layout, called Layout Builder, that has dynamic rows for the fields. 💾 [Build file](https://www.dropbox.com/scl/fi/zh4uqp6yidb1zkqqs98bh/gravityview-2.32-33bacbeef.zip?rlkey=w47ub1vhuj0pwetbjwmpb99w3&dl=1) (33bacbe).
2 parents 26370fd + a42ad3b commit 3f0f199

23 files changed

+611
-6
lines changed

assets/css/admin-entries-list.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/css/admin-global.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/css/admin-views.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/js/admin-views.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2558,10 +2558,10 @@
25582558
revert: 75,
25592559
connectWith: ".active-drop-field",
25602560
start: function( event, ui ) {
2561-
$( panel ).find( ".active-drop-container-field" ).addClass('is-receivable');
2561+
$( document.body ).find( ".active-drop-container-field" ).addClass('is-receivable');
25622562
},
25632563
stop: function( event, ui ) {
2564-
$( panel ).find( ".active-drop-container-field" ).removeClass('is-receivable');
2564+
$( document.body ).find( ".active-drop-container-field" ).removeClass('is-receivable');
25652565
},
25662566
change: function( event, ui ) {
25672567
vcfg.setUnsavedChanges( true );

assets/js/admin-views.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
namespace GV;
3+
4+
/** If this file is called directly, abort. */
5+
if ( ! defined( 'GRAVITYVIEW_DIR' ) ) {
6+
die();
7+
}
8+
9+
require_once 'trait-gv-field-renderer.php';
10+
11+
/**
12+
* The single Entry template.
13+
*
14+
* @since $ver$
15+
*/
16+
final class Entry_Layout_Builder_Template extends Entry_Template {
17+
use Field_Renderer_Trait;
18+
/**
19+
* {@inheritDoc}
20+
*
21+
* @since $ver$
22+
*
23+
* @var string
24+
*/
25+
public static $slug = \GravityView_Layout_Builder::ID;
26+
}

future/includes/class-gv-template-entry.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,4 @@ public function get_back_label( $do_replace = true ) {
184184
require gravityview()->plugin->dir( 'future/includes/class-gv-template-entry-table.php' );
185185
require gravityview()->plugin->dir( 'future/includes/class-gv-template-entry-list.php' );
186186
require gravityview()->plugin->dir( 'future/includes/class-gv-template-entry-legacy.php' );
187+
require gravityview()->plugin->dir( 'future/includes/class-gv-template-entry-layout-builder.php' );
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
namespace GV;
3+
4+
/** If this file is called directly, abort. */
5+
if ( ! defined( 'GRAVITYVIEW_DIR' ) ) {
6+
die();
7+
}
8+
9+
require_once 'trait-gv-field-renderer.php';
10+
11+
/**
12+
* The View template.
13+
*
14+
* @since $ver$
15+
*/
16+
final class View_Layout_Builder_Template extends View_Template {
17+
use Field_Renderer_Trait;
18+
19+
/**
20+
* {@inheritDoc}
21+
*
22+
* @since $ver$
23+
*
24+
* @var string
25+
*/
26+
public static $slug = \GravityView_Layout_Builder::ID;
27+
}

future/includes/class-gv-template-view.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,4 @@ public function render() {
158158
require gravityview()->plugin->dir( 'future/includes/class-gv-template-view-table.php' );
159159
require gravityview()->plugin->dir( 'future/includes/class-gv-template-view-list.php' );
160160
require gravityview()->plugin->dir( 'future/includes/class-gv-template-view-legacy.php' );
161+
require gravityview()->plugin->dir( 'future/includes/class-gv-template-view-layout-builder.php' );
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
namespace GV;
3+
4+
/**
5+
* Trait responsible for rendering a single field for an entry.
6+
*
7+
* @since $ver$
8+
*/
9+
trait Field_Renderer_Trait {
10+
/**
11+
* Output the field in the diy view.
12+
*
13+
* @param Field $field The field to output.
14+
* @param Entry $entry The entry.
15+
* @param array $extras Extra stuff, like wpautop, etc.
16+
*
17+
* @return string The field HTML.
18+
*/
19+
public function the_field( Field $field, Entry $entry, array $extras = [] ): string {
20+
$form = $this->view->form;
21+
22+
$context = Template_Context::from_template( $this, compact( 'field', 'entry' ) );
23+
24+
$renderer = new Field_Renderer();
25+
$source = is_numeric( $field->ID ) ? $this->view->form : new Internal_Source();
26+
27+
$value = $renderer->render( $field, $this->view, $source, $entry, $this->request );
28+
$label = apply_filters(
29+
'gravityview/template/field_label',
30+
$field->get_label( $this->view, $form ),
31+
$field->as_configuration(),
32+
$form->form ?: null,
33+
null,
34+
);
35+
36+
/**
37+
* @filter `gravityview/template/field/label` Override the field label.
38+
* @since 2.0
39+
*
40+
* @param [in,out] string $label The label to override.
41+
* @param \GV\Template_Context $context The context.
42+
*/
43+
$label = apply_filters( 'gravityview/template/field/label', $label, $context );
44+
45+
/**
46+
* @filter `gravityview/template/table/entry/hide_empty`
47+
*
48+
* @param boolean $hide_empty Should the row be hidden if the value is empty? Default: don't hide.
49+
* @param \GV\Template_Context $context The context ;) Love it, cherish it. And don't you dare modify it!
50+
*/
51+
$hide_empty = apply_filters(
52+
'gravityview/render/hide-empty-zone',
53+
Utils::get( $extras, 'hide_empty', $this->view->settings->get( 'hide_empty', false ) ),
54+
$context,
55+
);
56+
57+
$markup = '<div id="{{ field_id }}" class="{{ class }}">
58+
{{ label }}
59+
<div class="gv-grid-value">{{ value }}</div>
60+
</div>';
61+
62+
$extras = array_merge( $extras, compact( 'hide_empty', 'value', 'label', 'markup' ) );
63+
64+
return \gravityview_field_output( $extras, $context );
65+
}
66+
}

includes/presets/layout-builder/Template/FieldRenderer.php

Whitespace-only changes.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<?php
2+
3+
use GV\Entry_Layout_Builder_Template;
4+
use GV\Field_Collection;
5+
use GV\Grid;
6+
use GV\View_Layout_Builder_Template;
7+
8+
/**
9+
* Registers the Layout Builder Layout.
10+
*
11+
* @since $ver$
12+
*/
13+
final class GravityView_Layout_Builder extends GravityView_Template {
14+
/**
15+
* The Layout ID.
16+
*
17+
* @since $ver$
18+
*
19+
* @var string
20+
*/
21+
public const ID = 'gravityview-layout-builder';
22+
23+
/**
24+
* Creates the layout.
25+
*
26+
* @since $ver$
27+
*/
28+
public function __construct() {
29+
$areas = Grid::prefixed(
30+
self::ID,
31+
static fn() => [ Grid::get_row_by_type( '100' ) ],
32+
);
33+
34+
parent::__construct(
35+
self::ID,
36+
[
37+
'slug' => self::ID,
38+
'type' => 'custom',
39+
'label' => __( 'Layout Builder', 'gk-gravityview' ),
40+
'description' => __(
41+
'Display items in customizable rows and columns.',
42+
'gk-gravityview',
43+
),
44+
'css_source' => null,
45+
'logo' => plugins_url( 'includes/presets/layout-builder/logo-layout-builder.svg', GRAVITYVIEW_FILE ),
46+
],
47+
[
48+
'show_as_link' => [
49+
'type' => 'checkbox',
50+
'label' => esc_html__( 'Link to single entry', 'gk-gravityview' ),
51+
'value' => false,
52+
'context' => 'directory',
53+
'priority' => 1190,
54+
'group' => 'display',
55+
],
56+
],
57+
$areas,
58+
);
59+
60+
add_filter( 'gravityview/template/view/class', [ __CLASS__, 'get_view_class' ] );
61+
add_filter( 'gravityview/template/entry/class', [ __CLASS__, 'get_view_class' ] );
62+
63+
add_filter( 'gk/gravityview/admin-views/view/is-dynamic', [ __CLASS__, 'make_dynamic' ], 5, 3 );
64+
add_filter( 'gk/gravityview/admin-views/view/template/active-areas', [ __CLASS__, 'replace_active_areas' ], 5, 4 );
65+
66+
add_action( 'wp_enqueue_scripts', [ __CLASS__, 'register_style_assets' ] );
67+
}
68+
69+
/**
70+
* Returns {@see ViewTemplate} class name to be used as the View template class.
71+
*
72+
* @used-by `gravityview/template/view/class` filter.
73+
*
74+
* @since TBD
75+
*
76+
* @param string $template_class View template class.
77+
*
78+
* @return string The template class to use.
79+
*/
80+
public static function get_view_class( string $template_class ): string {
81+
// GravityView expects the class to be in the "GV\View_<name>_Template" format.
82+
$is_layout_builder_template = false !== stripos( $template_class, '_' . self::ID . '_' );
83+
if ( ! $is_layout_builder_template ) {
84+
return $template_class;
85+
}
86+
87+
return stripos( $template_class, 'view_' ) !== false
88+
? View_Layout_Builder_Template::class
89+
: Entry_Layout_Builder_Template::class;
90+
}
91+
92+
/**
93+
* Returns the dynamic areas, stored in the fields array.
94+
*
95+
* @since $ver$
96+
*
97+
* @param array $areas The current areas.
98+
* @param string $template_id The template ID.
99+
* @param string $context The context / zone.
100+
* @param array $fields The fields to render.
101+
*
102+
* @return array The rows with the active dynamic areas.
103+
*/
104+
public static function replace_active_areas(
105+
array $areas,
106+
string $template_id,
107+
string $context,
108+
array $fields
109+
): array {
110+
if ( self::ID !== $template_id ) {
111+
return $areas;
112+
}
113+
114+
$collection = Field_Collection::from_configuration( $fields );
115+
$rows = Grid::prefixed(
116+
self::ID,
117+
static fn() => Grid::get_rows_from_collection( $collection, $context ),
118+
);
119+
120+
return $rows ?: $areas;
121+
}
122+
123+
/**
124+
* Makes the field sections for the Layout Builder template sortable.
125+
*
126+
* @since $ver$
127+
*
128+
* @param bool $is_dynamic Whether it is dynamic.
129+
* @param string $template_id The template ID.
130+
* @param string $type The object type.
131+
*
132+
* @return bool Whether it is sortable
133+
*/
134+
public static function make_dynamic( bool $is_dynamic, string $template_id, string $type ): bool {
135+
if (
136+
self::ID !== $template_id
137+
|| 'field' !== $type
138+
) {
139+
return $is_dynamic;
140+
}
141+
142+
return true;
143+
}
144+
145+
/**
146+
* Registers the style assets for the View layout.
147+
*
148+
* @since $ver$
149+
*/
150+
public static function register_style_assets(): void {
151+
$style = 'gravityview_style_' . self::ID;
152+
wp_register_style(
153+
$style,
154+
plugin_dir_url( GRAVITYVIEW_FILE ) . 'templates/css/layout-builder.css',
155+
[],
156+
GV_PLUGIN_VERSION
157+
);
158+
}
159+
}
160+
161+
new GravityView_Layout_Builder();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<?php // Silence is golden
Lines changed: 1 addition & 0 deletions
Loading

includes/presets/register-default-templates.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function gravityview_register_default_templates() {
4040
include_once $path . 'resume-board/class-gravityview-preset-resume-board.php';
4141
include_once $path . 'job-board/class-gravityview-preset-job-board.php';
4242
include_once $path . 'event-listings/class-gravityview-preset-event-listings.php';
43+
include_once $path . 'layout-builder/class-gravityview-layout-builder.php';
4344
}
4445

4546

readme.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Beautifully display your Gravity Forms entries. Learn more on [gravitykit.com](h
2424
= develop =
2525

2626
#### 🚀 Added
27+
* New Layout Builder View type for creating custom layouts with single or multi-column configurations and adjustable widths.
2728
* `:initials` merge tag modifier for Name fields to display initials.
2829

2930
#### 🐛 Fixed

0 commit comments

Comments
 (0)