glib-web 4.17.0 → 4.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/helpers/glib/json_ui/view_builder/fields.rb +2 -0
- data/app/views/json_ui/garage/actions/_dialogs.json.jbuilder +4 -0
- data/app/views/json_ui/garage/actions/_dialogs_show.json.jbuilder +23 -9
- data/app/views/json_ui/garage/actions/_sheets.json.jbuilder +1 -1
- data/app/views/json_ui/garage/forms/_basic_content.json.jbuilder +47 -0
- data/app/views/json_ui/garage/forms/basic.json.jbuilder +2 -23
- data/app/views/json_ui/garage/forms/conditional_value.json.jbuilder +11 -0
- data/app/views/json_ui/garage/forms/pickers.json.jbuilder +18 -0
- data/app/views/json_ui/garage/tables/index.json.jbuilder +3 -0
- data/app/views/json_ui/garage/tables/nested_table.json.jbuilder +60 -0
- metadata +3 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 82f79da54bb6dc84ffc68665e5b67b17a333a7f30d080d38daa10149dfa5e151
         | 
| 4 | 
            +
              data.tar.gz: 4285bb6b341dd126a71b5a78d7e15b62101878bbb4c3652c769369f62dddd5b9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 248c2b369209b8162ed63d9235cb2251bb3075d18fa87581844b55af0f0a117256b863af78e7734a0b1c3fb7f3c21ebd7eebfd09fb758efc05c7b608934638f4
         | 
| 7 | 
            +
              data.tar.gz: 6353a2fde95a69aa82ff4039b998f84d260a8bc9a8bb7ad321d8335da33c9fe5e7297d9b23b100d1c9f29dd8c5be3758956e162bab6c2432b45ba95dc0367cfb
         | 
| @@ -436,6 +436,7 @@ class Glib::JsonUi::ViewBuilder | |
| 436 436 | 
             
                  date :max
         | 
| 437 437 | 
             
                  string :type
         | 
| 438 438 | 
             
                  bool :clearable
         | 
| 439 | 
            +
                  bool :buttonTemplate
         | 
| 439 440 |  | 
| 440 441 | 
             
                  # Override
         | 
| 441 442 | 
             
                  def value(value)
         | 
| @@ -449,6 +450,7 @@ class Glib::JsonUi::ViewBuilder | |
| 449 450 | 
             
                  date_time :min
         | 
| 450 451 | 
             
                  date_time :max
         | 
| 451 452 | 
             
                  bool :clearable
         | 
| 453 | 
            +
                  bool :buttonTemplate
         | 
| 452 454 | 
             
                end
         | 
| 453 455 |  | 
| 454 456 | 
             
                class Location < AbstractField
         | 
| @@ -44,6 +44,10 @@ section.rows builder: ->(template) do | |
| 44 44 | 
             
                render 'json_ui/garage/actions/dialogs_show', json: json, action: action, dialog_mode: :show
         | 
| 45 45 | 
             
              end
         | 
| 46 46 |  | 
| 47 | 
            +
              template.thumbnail title: 'dialogs/show (with form)', onClick: ->(action) do
         | 
| 48 | 
            +
                render 'json_ui/garage/actions/dialogs_show', json: json, action: action, dialog_mode: :show, include_form: true
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 47 51 | 
             
              template.thumbnail title: 'dialogs/open', onClick: ->(action) do
         | 
| 48 52 | 
             
                action.dialogs_open width: 950, url: json_ui_garage_url(path: 'forms/basic', mode: 'dialog'), disableCloseButton: true
         | 
| 49 53 | 
             
              end
         | 
| @@ -10,22 +10,36 @@ if (update_existing = local_assigns[:update_existing]) | |
| 10 10 | 
             
              options[:updateExisting] = update_existing
         | 
| 11 11 | 
             
            end
         | 
| 12 12 |  | 
| 13 | 
            +
            include_form = local_assigns[:include_form]
         | 
| 14 | 
            +
             | 
| 13 15 | 
             
            action.send "dialogs_#{dialog_mode}", **options, content: ->(dialog) do
         | 
| 14 16 | 
             
              dialog.body padding: glib_json_padding_body, childViews: ->(body) do
         | 
| 15 17 | 
             
                body.markdown text: markdown
         | 
| 16 18 |  | 
| 17 | 
            -
                 | 
| 18 | 
            -
                   | 
| 19 | 
            -
                     | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 19 | 
            +
                if include_form
         | 
| 20 | 
            +
                  render \
         | 
| 21 | 
            +
                    'json_ui/garage/forms/basic_content',
         | 
| 22 | 
            +
                    json: json,
         | 
| 23 | 
            +
                    panel: body,
         | 
| 24 | 
            +
                    mode: 'dialog',
         | 
| 25 | 
            +
                    disable_dirty_check: true
         | 
| 26 | 
            +
                else
         | 
| 27 | 
            +
                  body.panels_split width: 'matchParent', content: ->(split) do
         | 
| 28 | 
            +
                    split.left childViews: ->(left) do
         | 
| 29 | 
            +
                      left.panels_horizontal height: 'matchParent', align: 'middle', childViews: ->(horizontal) do
         | 
| 30 | 
            +
                        horizontal.label text: 'Open current', onClick: ->(subaction) do
         | 
| 31 | 
            +
                          subaction.dialogs_open \
         | 
| 32 | 
            +
                            width: 900,
         | 
| 33 | 
            +
                            fullscreen: 'mobile',
         | 
| 34 | 
            +
                            url: json_ui_garage_url(path: 'forms/basic')
         | 
| 35 | 
            +
                        end
         | 
| 22 36 | 
             
                      end
         | 
| 23 37 | 
             
                    end
         | 
| 24 | 
            -
                  end
         | 
| 25 38 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 39 | 
            +
                    split.right childViews: ->(right) do
         | 
| 40 | 
            +
                      right.button text: 'Open New', onClick: ->(subaction) do
         | 
| 41 | 
            +
                        subaction.dialogs_open url: json_ui_garage_url(path: 'forms/basic', mode: 'dialog')
         | 
| 42 | 
            +
                      end
         | 
| 29 43 | 
             
                    end
         | 
| 30 44 | 
             
                  end
         | 
| 31 45 | 
             
                end
         | 
| @@ -6,7 +6,7 @@ end | |
| 6 6 | 
             
            section.rows builder: ->(template) do
         | 
| 7 7 | 
             
              template.thumbnail title: 'sheets/select', onClick: ->(action) do
         | 
| 8 8 | 
             
                action.sheets_select message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed rutrum vel nisi in pharetra. Aenean mollis feugiat elementum. Donec tempor arcu fringilla risus finibus cursus. Donec eleifend ex sit amet odio rutrum, vitae ornare nunc congue. In hac habitasse platea dictumst. Curabitur at velit et odio ornare vestibulum sit amet vitae ex. Proin tincidunt rutrum libero vitae tempus.', buttons: ->(menu) do
         | 
| 9 | 
            -
                  menu.button text: 'Option1', onClick: ->(subaction) do
         | 
| 9 | 
            +
                  menu.button text: 'Option1 Aenean mollis feugiat elementum. Donec tempor arcu fringilla risus finibus cursus.', onClick: ->(subaction) do
         | 
| 10 10 | 
             
                    subaction.dialogs_alert message: 'Option 1'
         | 
| 11 11 | 
             
                  end
         | 
| 12 12 | 
             
                  menu.button text: 'Option2', onClick: ->(subaction) do
         | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            disable_dirty_check = local_assigns[:disable_dirty_check]
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            panel.panels_form url: json_ui_garage_url(path: 'forms/basic_post'), method: 'post', padding: glib_json_padding_body, childViews: ->(form) do
         | 
| 4 | 
            +
              form.fields_text name: 'user[name]', width: 'matchParent', label: 'Name', disableDirtyCheck: disable_dirty_check
         | 
| 5 | 
            +
              form.fields_password name: 'user[password]', width: 'matchParent', label: 'Password', disableDirtyCheck: disable_dirty_check
         | 
| 6 | 
            +
              form.fields_text name: 'user[title]', width: 'matchParent', label: 'Title', disableDirtyCheck: disable_dirty_check
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              form.fields_select width: 'matchParent', name: 'user[types]', options: [
         | 
| 9 | 
            +
                { value: 1, text: 'One' },
         | 
| 10 | 
            +
                { value: 2, text: 'Two' }
         | 
| 11 | 
            +
              ], disableDirtyCheck: disable_dirty_check
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              form.fields_checkGroup disableDirtyCheck: disable_dirty_check, width: 'matchParent', name: 'user[multichoices]', childViews: ->(group) do
         | 
| 14 | 
            +
                group.fields_check label: 'Choice 1', checkValue: 'choice1'
         | 
| 15 | 
            +
                group.fields_check label: 'Choice 2', checkValue: 'choice2'
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              form.panels_split width: 'matchParent', content: ->(split) do
         | 
| 19 | 
            +
                split.left childViews: ->(left) do
         | 
| 20 | 
            +
                  left.panels_horizontal height: 'matchParent', align: 'middle', childViews: ->(horizontal) do
         | 
| 21 | 
            +
                    mode = local_assigns[:mode]
         | 
| 22 | 
            +
                    case mode || params[:mode]
         | 
| 23 | 
            +
                    when 'dialog'
         | 
| 24 | 
            +
                      horizontal.fields_hidden name: 'mode', value: 'dialog'
         | 
| 25 | 
            +
                      horizontal.button styleClass: 'link', text: 'cancel', onClick: ->(action) { action.dialogs_close }
         | 
| 26 | 
            +
                    when 'dialog_reload'
         | 
| 27 | 
            +
                      horizontal.button styleClass: 'link', text: 'back', onClick: ->(action) do
         | 
| 28 | 
            +
                        render 'json_ui/garage/actions/dialogs_show', json: json, action: action, dialog_mode: :reload
         | 
| 29 | 
            +
                      end
         | 
| 30 | 
            +
                    when 'dialog_show'
         | 
| 31 | 
            +
                      horizontal.button styleClass: 'link', text: 'show', onClick: ->(action) do
         | 
| 32 | 
            +
                        render \
         | 
| 33 | 
            +
                          'json_ui/garage/actions/dialogs_show',
         | 
| 34 | 
            +
                          json: json,
         | 
| 35 | 
            +
                          action: action,
         | 
| 36 | 
            +
                          dialog_mode: :show,
         | 
| 37 | 
            +
                          include_form: true
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
                split.right childViews: ->(right) do
         | 
| 43 | 
            +
                  # right.button text: 'Submit', onClick: ->(action) { action.forms_submit }
         | 
| 44 | 
            +
                  right.fields_submit text: 'Submit'
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         | 
| @@ -3,27 +3,6 @@ json.title 'Forms' | |
| 3 3 | 
             
            page = json_ui_page json
         | 
| 4 4 | 
             
            render "#{@path_prefix}/nav_menu", json: json, page: page
         | 
| 5 5 |  | 
| 6 | 
            -
            page. | 
| 7 | 
            -
               | 
| 8 | 
            -
              form.fields_password name: 'user[password]', width: 'matchParent', label: 'Password'
         | 
| 9 | 
            -
             | 
| 10 | 
            -
              form.panels_split width: 'matchParent', content: ->(split) do
         | 
| 11 | 
            -
                split.left childViews: ->(left) do
         | 
| 12 | 
            -
                  left.panels_horizontal height: 'matchParent', align: 'middle', childViews: ->(horizontal) do
         | 
| 13 | 
            -
                    case params[:mode]
         | 
| 14 | 
            -
                    when 'dialog'
         | 
| 15 | 
            -
                      horizontal.fields_hidden name: 'mode', value: 'dialog'
         | 
| 16 | 
            -
                      horizontal.button styleClass: 'link', text: 'cancel', onClick: ->(action) { action.dialogs_close }
         | 
| 17 | 
            -
                    when 'dialog_reload'
         | 
| 18 | 
            -
                      horizontal.button styleClass: 'link', text: 'back', onClick: ->(action) do
         | 
| 19 | 
            -
                        render 'json_ui/garage/actions/dialogs_show', json: json, action: action, dialog_mode: :reload
         | 
| 20 | 
            -
                      end
         | 
| 21 | 
            -
                    end
         | 
| 22 | 
            -
                  end
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
                split.right childViews: ->(right) do
         | 
| 25 | 
            -
                  # right.button text: 'Submit', onClick: ->(action) { action.forms_submit }
         | 
| 26 | 
            -
                  right.fields_submit text: 'Submit'
         | 
| 27 | 
            -
                end
         | 
| 28 | 
            -
              end
         | 
| 6 | 
            +
            page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
         | 
| 7 | 
            +
              render 'json_ui/garage/forms/basic_content', panel: scroll
         | 
| 29 8 | 
             
            end
         | 
| @@ -26,6 +26,17 @@ page.form \ | |
| 26 26 | 
             
                end
         | 
| 27 27 | 
             
                form.fields_datetime id: 'date2', name: 'user[datetime_end]', width: 'matchParent', label: 'End Date', min: '2010-01-01', max: '2012-01-01'
         | 
| 28 28 |  | 
| 29 | 
            +
                form.spacer height: 20
         | 
| 30 | 
            +
                form.h2 text: 'Button Date'
         | 
| 31 | 
            +
                form.label text: 'Plus 30 days'
         | 
| 32 | 
            +
                form.spacer height: 6
         | 
| 33 | 
            +
                form.fields_date name: 'user[date_start1]', label: 'Add start date', value: '2024-12-12', buttonTemplate: true, onChange: ->(action) do
         | 
| 34 | 
            +
                  action.logics_set targetId: 'date3', conditionalData: { value: { "sum_date": [{ "var": 'user[date_start1]' }, { value: 86400 * 30, format: 'date' }] } }
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
                form.spacer height: 6
         | 
| 37 | 
            +
                form.fields_date id: 'date3', name: 'user[date_end1]', label: 'End date', buttonTemplate: true
         | 
| 38 | 
            +
             | 
| 39 | 
            +
             | 
| 29 40 | 
             
                form.spacer height: 20
         | 
| 30 41 | 
             
                form.h2 text: 'Divided by 3 (with precision set)'
         | 
| 31 42 | 
             
                form.spacer height: 6
         | 
| @@ -70,6 +70,8 @@ page.form \ | |
| 70 70 | 
             
                max: '2021-03-01',
         | 
| 71 71 | 
             
                value: '2021-11'
         | 
| 72 72 |  | 
| 73 | 
            +
             | 
| 74 | 
            +
             | 
| 73 75 | 
             
              if record.present?
         | 
| 74 76 | 
             
                form.fields_datetime \
         | 
| 75 77 | 
             
                  prop: :created_at,
         | 
| @@ -78,6 +80,22 @@ page.form \ | |
| 78 80 | 
             
                  width: 'matchParent'
         | 
| 79 81 | 
             
              end
         | 
| 80 82 |  | 
| 83 | 
            +
              form.spacer height: 8
         | 
| 84 | 
            +
              form.fields_date \
         | 
| 85 | 
            +
                name: 'user[due_date]',
         | 
| 86 | 
            +
                label: 'Add due date',
         | 
| 87 | 
            +
                buttonTemplate: true,
         | 
| 88 | 
            +
                min: '2024-11-01',
         | 
| 89 | 
            +
                max: '2024-12-31'
         | 
| 90 | 
            +
              form.spacer height: 8
         | 
| 91 | 
            +
             | 
| 92 | 
            +
              form.spacer height: 8
         | 
| 93 | 
            +
              form.fields_datetime \
         | 
| 94 | 
            +
                name: 'user[due_date1]',
         | 
| 95 | 
            +
                label: 'Add due datetime',
         | 
| 96 | 
            +
                buttonTemplate: true
         | 
| 97 | 
            +
              form.spacer height: 8
         | 
| 98 | 
            +
             | 
| 81 99 | 
             
              form.spacer height: 20
         | 
| 82 100 | 
             
              form.h2 text: 'Country'
         | 
| 83 101 | 
             
              form.spacer height: 6
         | 
| @@ -8,6 +8,9 @@ page.list firstSection: ->(section) do | |
| 8 8 | 
             
                template.thumbnail title: 'Layout', onClick: ->(action) do
         | 
| 9 9 | 
             
                  action.windows_open url: json_ui_garage_url(path: 'tables/layout')
         | 
| 10 10 | 
             
                end
         | 
| 11 | 
            +
                template.thumbnail title: 'Nested table', onClick: ->(action) do
         | 
| 12 | 
            +
                  action.windows_open url: json_ui_garage_url(path: 'tables/nested_table')
         | 
| 13 | 
            +
                end
         | 
| 11 14 | 
             
                template.thumbnail title: 'Horizontal Scroll', onClick: ->(action) do
         | 
| 12 15 | 
             
                  action.windows_open url: json_ui_garage_url(path: 'tables/horizontal_scroll')
         | 
| 13 16 | 
             
                end
         | 
| @@ -0,0 +1,60 @@ | |
| 1 | 
            +
            json.title 'Tables'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            page = json_ui_page json
         | 
| 4 | 
            +
            render "#{@path_prefix}/nav_menu", json: json, page: page
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            page.form width: 'matchParent', childViews: ->(view) do
         | 
| 7 | 
            +
              view.panels_table styleClass: 'table--plain', sections: [
         | 
| 8 | 
            +
                ->(section) do
         | 
| 9 | 
            +
                  section.header cellViews: ->(header) do
         | 
| 10 | 
            +
                    header.label text: ''
         | 
| 11 | 
            +
                    header.label text: 'Month'
         | 
| 12 | 
            +
                    header.label text: 'Electicity'
         | 
| 13 | 
            +
                    header.label text: 'Sanitation Facility'
         | 
| 14 | 
            +
                    header.label text: 'Ground Irrigation'
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  items = [
         | 
| 18 | 
            +
                    { month: 'Jan', electricity: 1200, sanitation_facility: 500, ground_irrigation: 450 },
         | 
| 19 | 
            +
                    { month: 'Feb', electricity: 1150, sanitation_facility: 800, ground_irrigation: 440 },
         | 
| 20 | 
            +
                    { month: 'Mar', electricity: 1100, sanitation_facility: 700, ground_irrigation: 430 },
         | 
| 21 | 
            +
                    { month: 'Apr', electricity: 1000, sanitation_facility: 450, ground_irrigation: 420 }
         | 
| 22 | 
            +
                  ]
         | 
| 23 | 
            +
                  section.rows objects: items, builder: ->(row, item, index) do
         | 
| 24 | 
            +
                    row.default cellViews: ->(cell) do
         | 
| 25 | 
            +
                      cell.fields_check name: "row-#{index}", onIcon: 'keyboard_arrow_up', offIcon: 'keyboard_arrow_down', checkValue: true, onChange: ->(action) do
         | 
| 26 | 
            +
                      action.logics_set targetId: "nested-#{index}", conditionalData: {
         | 
| 27 | 
            +
                        displayed: { "var": "row-#{index}" }
         | 
| 28 | 
            +
                      }
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                      cell.label text: item[:month]
         | 
| 31 | 
            +
                      cell.label text: item[:electricity]
         | 
| 32 | 
            +
                      cell.label text: item[:sanitation_facility]
         | 
| 33 | 
            +
                      cell.label text: item[:ground_irrigation]
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                    row.default colSpans: [5], cellViews: ->(cell) do
         | 
| 36 | 
            +
                      cell.panels_table id: "nested-#{index}", displayed: false, width: 'matchParent', sections: [
         | 
| 37 | 
            +
                        ->(ssection) do
         | 
| 38 | 
            +
                          ssection.header cellViews: ->(header) do
         | 
| 39 | 
            +
                            header.label text: 'Filename'
         | 
| 40 | 
            +
                            header.label text: 'Uploaded At'
         | 
| 41 | 
            +
                            header.label text: ''
         | 
| 42 | 
            +
                          end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                          sitems = [
         | 
| 45 | 
            +
                            { filename: 'electricity-bill.png', uploaded_at: '2024-05-11' },
         | 
| 46 | 
            +
                            { filename: 'irrigation-bill.png', uploaded_at: '2024-05-11' }
         | 
| 47 | 
            +
                          ]
         | 
| 48 | 
            +
                          ssection.rows objects: sitems, builder: ->(srow, sitem, sindex) do
         | 
| 49 | 
            +
                            srow.default cellViews: ->(scell) do
         | 
| 50 | 
            +
                              scell.label text: sitem[:filename]
         | 
| 51 | 
            +
                              scell.label text: sitem[:uploaded_at]
         | 
| 52 | 
            +
                            end
         | 
| 53 | 
            +
                          end
         | 
| 54 | 
            +
                        end
         | 
| 55 | 
            +
                      ]
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
              ]
         | 
| 60 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: glib-web
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 4. | 
| 4 | 
            +
              version: 4.18.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - ''
         | 
| @@ -198,6 +198,7 @@ files: | |
| 198 198 | 
             
            - app/views/json_ui/garage/empty.json.jbuilder
         | 
| 199 199 | 
             
            - app/views/json_ui/garage/forms/_alert_post_all_data.json.jbuilder
         | 
| 200 200 | 
             
            - app/views/json_ui/garage/forms/_alert_post_data.json.jbuilder
         | 
| 201 | 
            +
            - app/views/json_ui/garage/forms/_basic_content.json.jbuilder
         | 
| 201 202 | 
             
            - app/views/json_ui/garage/forms/_conditional_banner.json.jbuilder
         | 
| 202 203 | 
             
            - app/views/json_ui/garage/forms/_partial_update_execute.json.jbuilder
         | 
| 203 204 | 
             
            - app/views/json_ui/garage/forms/_read_more_text.json.jbuilder
         | 
| @@ -313,6 +314,7 @@ files: | |
| 313 314 | 
             
            - app/views/json_ui/garage/tables/horizontal_scroll.json.jbuilder
         | 
| 314 315 | 
             
            - app/views/json_ui/garage/tables/index.json.jbuilder
         | 
| 315 316 | 
             
            - app/views/json_ui/garage/tables/layout.json.jbuilder
         | 
| 317 | 
            +
            - app/views/json_ui/garage/tables/nested_table.json.jbuilder
         | 
| 316 318 | 
             
            - app/views/json_ui/garage/tables/panel_content.json.jbuilder
         | 
| 317 319 | 
             
            - app/views/json_ui/garage/test_page/_header.json.jbuilder
         | 
| 318 320 | 
             
            - app/views/json_ui/garage/test_page/auto_validate.json.jbuilder
         |