├── .babelrc
├── .browserslistrc
├── .gitattributes
├── .github
└── workflows
│ ├── release.yml
│ └── rspec.yml
├── .gitignore
├── .rspec
├── CONTRIBUTING.md
├── Gemfile
├── Guardfile
├── LICENSE
├── README.md
├── Rakefile
├── app
├── assets
│ ├── bundle
│ │ └── trestle
│ │ │ ├── admin.css
│ │ │ ├── admin.js
│ │ │ ├── fa-brands-400.ttf
│ │ │ ├── fa-brands-400.woff2
│ │ │ ├── fa-regular-400.ttf
│ │ │ ├── fa-regular-400.woff2
│ │ │ ├── fa-solid-900.ttf
│ │ │ ├── fa-solid-900.woff2
│ │ │ ├── locale
│ │ │ ├── cs.js
│ │ │ ├── de.js
│ │ │ ├── en.js
│ │ │ ├── es-MX.js
│ │ │ ├── es.js
│ │ │ ├── flatpickr
│ │ │ │ ├── ar-dz.js
│ │ │ │ ├── ar.js
│ │ │ │ ├── at.js
│ │ │ │ ├── az.js
│ │ │ │ ├── be.js
│ │ │ │ ├── bg.js
│ │ │ │ ├── bn.js
│ │ │ │ ├── bs.js
│ │ │ │ ├── cat.js
│ │ │ │ ├── ckb.js
│ │ │ │ ├── cs.js
│ │ │ │ ├── cy.js
│ │ │ │ ├── da.js
│ │ │ │ ├── de.js
│ │ │ │ ├── default.js
│ │ │ │ ├── eo.js
│ │ │ │ ├── es.js
│ │ │ │ ├── et.js
│ │ │ │ ├── fa.js
│ │ │ │ ├── fi.js
│ │ │ │ ├── fo.js
│ │ │ │ ├── fr.js
│ │ │ │ ├── ga.js
│ │ │ │ ├── gr.js
│ │ │ │ ├── he.js
│ │ │ │ ├── hi.js
│ │ │ │ ├── hr.js
│ │ │ │ ├── hu.js
│ │ │ │ ├── hy.js
│ │ │ │ ├── id.js
│ │ │ │ ├── is.js
│ │ │ │ ├── it.js
│ │ │ │ ├── ja.js
│ │ │ │ ├── ka.js
│ │ │ │ ├── km.js
│ │ │ │ ├── ko.js
│ │ │ │ ├── kz.js
│ │ │ │ ├── lt.js
│ │ │ │ ├── lv.js
│ │ │ │ ├── mk.js
│ │ │ │ ├── mn.js
│ │ │ │ ├── ms.js
│ │ │ │ ├── my.js
│ │ │ │ ├── nl.js
│ │ │ │ ├── nn.js
│ │ │ │ ├── no.js
│ │ │ │ ├── pa.js
│ │ │ │ ├── pl.js
│ │ │ │ ├── pt.js
│ │ │ │ ├── ro.js
│ │ │ │ ├── ru.js
│ │ │ │ ├── si.js
│ │ │ │ ├── sk.js
│ │ │ │ ├── sl.js
│ │ │ │ ├── sq.js
│ │ │ │ ├── sr-cyr.js
│ │ │ │ ├── sr.js
│ │ │ │ ├── sv.js
│ │ │ │ ├── th.js
│ │ │ │ ├── tr.js
│ │ │ │ ├── uk.js
│ │ │ │ ├── uz.js
│ │ │ │ ├── uz_latn.js
│ │ │ │ ├── vn.js
│ │ │ │ ├── zh-tw.js
│ │ │ │ └── zh.js
│ │ │ ├── fr.js
│ │ │ ├── ko.js
│ │ │ ├── lv.js
│ │ │ ├── nl.js
│ │ │ ├── pl.js
│ │ │ ├── pt-BR.js
│ │ │ ├── vi.js
│ │ │ └── zh-CN.js
│ │ │ └── photoswipe-2d522a3abaa59f8a8f73.digested.js
│ ├── javascripts
│ │ └── trestle
│ │ │ └── custom.js
│ ├── sprockets
│ │ └── trestle
│ │ │ ├── _custom.css
│ │ │ ├── custom.css
│ │ │ ├── icons
│ │ │ └── font-awesome.css.erb
│ │ │ └── manifest.js
│ └── stylesheets
│ │ └── trestle
│ │ └── custom.css
├── controllers
│ ├── concerns
│ │ └── trestle
│ │ │ ├── controller
│ │ │ ├── breadcrumbs.rb
│ │ │ ├── callbacks.rb
│ │ │ ├── helpers.rb
│ │ │ ├── layout.rb
│ │ │ ├── location.rb
│ │ │ ├── modal.rb
│ │ │ ├── title.rb
│ │ │ ├── toolbars.rb
│ │ │ └── turbo_stream.rb
│ │ │ └── resource
│ │ │ └── controller
│ │ │ ├── actions.rb
│ │ │ ├── data_methods.rb
│ │ │ ├── redirection.rb
│ │ │ └── toolbar.rb
│ └── trestle
│ │ ├── admin_controller.rb
│ │ ├── application_controller.rb
│ │ ├── dashboard_controller.rb
│ │ └── resource_controller.rb
├── helpers
│ └── trestle
│ │ ├── avatar_helper.rb
│ │ ├── card_helper.rb
│ │ ├── container_helper.rb
│ │ ├── display_helper.rb
│ │ ├── flash_helper.rb
│ │ ├── form_helper.rb
│ │ ├── format_helper.rb
│ │ ├── gravatar_helper.rb
│ │ ├── grid_helper.rb
│ │ ├── headings_helper.rb
│ │ ├── hook_helper.rb
│ │ ├── i18n_helper.rb
│ │ ├── icon_helper.rb
│ │ ├── layout_helper.rb
│ │ ├── modal_helper.rb
│ │ ├── navigation_helper.rb
│ │ ├── pagination_helper.rb
│ │ ├── params_helper.rb
│ │ ├── sort_helper.rb
│ │ ├── status_helper.rb
│ │ ├── tab_helper.rb
│ │ ├── table_helper.rb
│ │ ├── timestamp_helper.rb
│ │ ├── title_helper.rb
│ │ ├── toolbars_helper.rb
│ │ ├── turbo
│ │ ├── frame_helper.rb
│ │ ├── stream_helper.rb
│ │ └── tag_builder.rb
│ │ └── url_helper.rb
└── views
│ ├── kaminari
│ └── trestle
│ │ ├── _first_page.html.erb
│ │ ├── _gap.html.erb
│ │ ├── _last_page.html.erb
│ │ ├── _page.html.erb
│ │ └── _paginator.html.erb
│ ├── layouts
│ └── trestle
│ │ ├── admin.html.erb
│ │ └── modal.html.erb
│ └── trestle
│ ├── _i18n.html.erb
│ ├── _theme.html.erb
│ ├── admin
│ └── index.html.erb
│ ├── application
│ ├── _header.html.erb
│ ├── _layout.html.erb
│ ├── _modal.html.erb
│ ├── _tabs.html.erb
│ └── _utilities.html.erb
│ ├── dashboard
│ └── index.html.erb
│ ├── flash
│ ├── _alert.html.erb
│ ├── _debug.html.erb
│ └── _flash.html.erb
│ ├── resource
│ ├── _form.html.erb
│ ├── _scopes.html.erb
│ ├── _table.html.erb
│ ├── create.turbo_stream.erb
│ ├── destroy.turbo_stream.erb
│ ├── edit.html.erb
│ ├── index.html.erb
│ ├── new.html.erb
│ ├── show.html.erb
│ └── update.turbo_stream.erb
│ ├── shared
│ ├── _footer.html.erb
│ ├── _header.html.erb
│ ├── _sidebar.html.erb
│ └── _title.html.erb
│ └── table
│ ├── _pagination.html.erb
│ └── _table.html.erb
├── bin
├── console
└── setup
├── config
├── locales
│ ├── cs.rb
│ ├── cs.yml
│ ├── de.rb
│ ├── de.yml
│ ├── en.rb
│ ├── en.yml
│ ├── es-MX.yml
│ ├── es.yml
│ ├── fr.rb
│ ├── fr.yml
│ ├── ko.rb
│ ├── ko.yml
│ ├── lv.rb
│ ├── lv.yml
│ ├── nl.rb
│ ├── nl.yml
│ ├── pl.rb
│ ├── pl.yml
│ ├── pt-BR.rb
│ ├── pt-BR.yml
│ ├── vi.rb
│ ├── vi.yml
│ ├── zh-CN.rb
│ └── zh-CN.yml
└── routes.rb
├── frontend
├── css
│ ├── _support.scss
│ ├── components
│ │ ├── _alerts.scss
│ │ ├── _avatar.scss
│ │ ├── _background.scss
│ │ ├── _badges.scss
│ │ ├── _breadcrumbs.scss
│ │ ├── _buttons.scss
│ │ ├── _datepicker.scss
│ │ ├── _dropdown.scss
│ │ ├── _forms.scss
│ │ ├── _grid.scss
│ │ ├── _media-grid.scss
│ │ ├── _modal.scss
│ │ ├── _pagination.scss
│ │ ├── _photoswipe.scss
│ │ ├── _popover.scss
│ │ ├── _scopes.scss
│ │ ├── _select.scss
│ │ ├── _sort.scss
│ │ ├── _table.scss
│ │ ├── _tabs.scss
│ │ ├── _tags.scss
│ │ ├── _timestamp.scss
│ │ ├── _toolbars.scss
│ │ └── _turbo.scss
│ ├── core
│ │ ├── _bootstrap.scss
│ │ ├── _dependencies.scss
│ │ ├── _functions.scss
│ │ ├── _mixins.scss
│ │ ├── _theme.scss
│ │ └── _typography.scss
│ ├── icons
│ │ └── _fontawesome.scss
│ ├── index.scss
│ ├── layout
│ │ ├── _base.scss
│ │ ├── _content-header.scss
│ │ ├── _footer.scss
│ │ ├── _header.scss
│ │ ├── _main-content.scss
│ │ ├── _navigation.scss
│ │ └── _sidebar.scss
│ ├── support
│ │ ├── _sprockets.scss
│ │ └── _webpack.scss
│ └── variables
│ │ ├── _bootstrap.scss
│ │ ├── _maps.scss
│ │ └── _trestle.scss
├── images
│ └── bright-squares.png
├── index.js
└── js
│ ├── controllers
│ ├── application_controller.js
│ ├── batch_action_controller.js
│ ├── checkbox_select_controller.js
│ ├── confirm_controller.js
│ ├── confirm_delete_controller.js
│ ├── datepicker_controller.js
│ ├── datetimepicker_controller.js
│ ├── deprecated
│ │ └── init_controller.js
│ ├── flatpickr_controller.js
│ ├── follow_url_controller.js
│ ├── form_error_controller.js
│ ├── form_loading_controller.js
│ ├── gallery_controller.js
│ ├── index.js
│ ├── keyboard_submit_controller.js
│ ├── lightbox_controller.js
│ ├── mobile_sidebar_controller.js
│ ├── modal_controller.js
│ ├── modal_frame_controller.js
│ ├── modal_trigger_controller.js
│ ├── navigation_controller.js
│ ├── navigation_tooltip_controller.js
│ ├── popover_controller.js
│ ├── reloadable_controller.js
│ ├── select_controller.js
│ ├── sidebar_controller.js
│ ├── tab_errors_controller.js
│ ├── tabs_controller.js
│ ├── timepicker_controller.js
│ ├── toggle_attr_controller.js
│ ├── toggle_class_controller.js
│ ├── tooltip_controller.js
│ └── wrapper_controller.js
│ ├── core
│ ├── backdrop.js
│ ├── cookie.js
│ ├── error_modal.js
│ ├── fetch.js
│ ├── i18n.js
│ ├── modal.js
│ ├── stream_actions.js
│ └── turbo_errors.js
│ ├── deprecated
│ ├── events.js
│ └── tooltip.js
│ ├── index.js
│ ├── mixins
│ ├── index.js
│ └── photoswipe.js
│ └── util
│ └── bootstrap.js
├── gemfiles
├── rails-6.0.gemfile
├── rails-6.1.gemfile
├── rails-7.0-propshaft.gemfile
├── rails-7.0.gemfile
├── rails-7.1-propshaft.gemfile
├── rails-7.1-sassc-rails.gemfile
├── rails-7.1.gemfile
├── rails-7.2-propshaft.gemfile
├── rails-7.2.gemfile
├── rails-8.0-propshaft.gemfile
└── rails-8.0.gemfile
├── i18n
├── config.yml
├── environment.rb
├── export
└── template.erb
├── lib
├── generators
│ └── trestle
│ │ ├── admin
│ │ ├── admin_generator.rb
│ │ └── templates
│ │ │ ├── admin.rb.erb
│ │ │ └── index.html.erb
│ │ ├── install
│ │ ├── install_generator.rb
│ │ └── templates
│ │ │ ├── _custom.css
│ │ │ ├── _custom.scss
│ │ │ ├── custom.js
│ │ │ └── trestle.rb.erb
│ │ └── resource
│ │ ├── resource_generator.rb
│ │ └── templates
│ │ └── admin.rb.erb
├── trestle.rb
└── trestle
│ ├── adapters.rb
│ ├── adapters
│ ├── active_record_adapter.rb
│ ├── adapter.rb
│ ├── draper_adapter.rb
│ └── sequel_adapter.rb
│ ├── admin.rb
│ ├── admin
│ └── builder.rb
│ ├── attribute.rb
│ ├── breadcrumb.rb
│ ├── builder.rb
│ ├── color.rb
│ ├── configurable.rb
│ ├── configuration.rb
│ ├── debug_errors.rb
│ ├── display.rb
│ ├── engine.rb
│ ├── evaluation_context.rb
│ ├── form.rb
│ ├── form
│ ├── automatic.rb
│ ├── builder.rb
│ ├── field.rb
│ ├── fields.rb
│ ├── fields
│ │ ├── check_box.rb
│ │ ├── check_box_helpers.rb
│ │ ├── collection_check_boxes.rb
│ │ ├── collection_radio_buttons.rb
│ │ ├── collection_select.rb
│ │ ├── color_field.rb
│ │ ├── date_field.rb
│ │ ├── date_picker.rb
│ │ ├── date_select.rb
│ │ ├── datetime_field.rb
│ │ ├── datetime_select.rb
│ │ ├── email_field.rb
│ │ ├── file_field.rb
│ │ ├── form_control.rb
│ │ ├── form_group.rb
│ │ ├── grouped_collection_select.rb
│ │ ├── month_field.rb
│ │ ├── number_field.rb
│ │ ├── password_field.rb
│ │ ├── radio_button.rb
│ │ ├── radio_button_helpers.rb
│ │ ├── range_field.rb
│ │ ├── search_field.rb
│ │ ├── select.rb
│ │ ├── static_field.rb
│ │ ├── tag_select.rb
│ │ ├── telephone_field.rb
│ │ ├── text_area.rb
│ │ ├── text_field.rb
│ │ ├── time_field.rb
│ │ ├── time_select.rb
│ │ ├── time_zone_select.rb
│ │ ├── url_field.rb
│ │ └── week_field.rb
│ └── renderer.rb
│ ├── hook.rb
│ ├── hook
│ ├── helpers.rb
│ └── set.rb
│ ├── lazy.rb
│ ├── model_name.rb
│ ├── navigation.rb
│ ├── navigation
│ ├── block.rb
│ ├── group.rb
│ └── item.rb
│ ├── options.rb
│ ├── registry.rb
│ ├── reloader.rb
│ ├── resource.rb
│ ├── resource
│ ├── adapter_methods.rb
│ ├── builder.rb
│ ├── collection.rb
│ └── toolbar.rb
│ ├── scopes.rb
│ ├── scopes
│ ├── block.rb
│ ├── definition.rb
│ └── scope.rb
│ ├── sprockets_compressor.rb
│ ├── tab.rb
│ ├── table.rb
│ ├── table
│ ├── actions_column.rb
│ ├── automatic.rb
│ ├── builder.rb
│ ├── column.rb
│ ├── row.rb
│ └── select_column.rb
│ ├── toolbar.rb
│ ├── toolbar
│ ├── builder.rb
│ ├── context.rb
│ ├── item.rb
│ └── menu.rb
│ └── version.rb
├── package.json
├── sandbox
├── Rakefile
├── app
│ ├── admin
│ │ ├── articles_admin.rb
│ │ ├── categories_admin.rb
│ │ ├── components
│ │ │ ├── alerts_admin.rb
│ │ │ ├── buttons_admin.rb
│ │ │ ├── forms_admin.rb
│ │ │ ├── grid_admin.rb
│ │ │ ├── icons_admin.rb
│ │ │ ├── media_admin.rb
│ │ │ ├── miscellaneous_admin.rb
│ │ │ ├── theme_admin.rb
│ │ │ └── typography_admin.rb
│ │ ├── offices_admin.rb
│ │ └── users_admin.rb
│ ├── assets
│ │ ├── config
│ │ │ └── manifest.js
│ │ ├── images
│ │ │ ├── .keep
│ │ │ ├── logo-small.svg
│ │ │ └── logo.svg
│ │ ├── javascripts
│ │ │ ├── application.js
│ │ │ └── trestle
│ │ │ │ ├── custom.js
│ │ │ │ └── custom
│ │ │ │ └── controllers
│ │ │ │ ├── modal_demo
│ │ │ │ ├── modal_controller.js
│ │ │ │ └── trigger_controller.js
│ │ │ │ └── theme_controller.js
│ │ └── stylesheets
│ │ │ ├── application.css
│ │ │ └── trestle
│ │ │ └── _custom.css
│ ├── channels
│ │ └── application_cable
│ │ │ ├── channel.rb
│ │ │ └── connection.rb
│ ├── controllers
│ │ ├── application_controller.rb
│ │ └── concerns
│ │ │ └── .keep
│ ├── fields
│ │ └── custom_field.rb
│ ├── helpers
│ │ ├── application_helper.rb
│ │ └── image_helper.rb
│ ├── jobs
│ │ └── application_job.rb
│ ├── mailers
│ │ └── application_mailer.rb
│ ├── models
│ │ ├── application_record.rb
│ │ ├── article.rb
│ │ ├── category.rb
│ │ ├── color.rb
│ │ ├── concerns
│ │ │ └── .keep
│ │ ├── font_awesome.rb
│ │ ├── office.rb
│ │ └── user.rb
│ └── views
│ │ ├── admin
│ │ └── components
│ │ │ ├── alerts
│ │ │ └── index.html.erb
│ │ │ ├── buttons
│ │ │ ├── _basic.html.erb
│ │ │ ├── _dropdowns.html.erb
│ │ │ ├── _groups.html.erb
│ │ │ ├── _icon.html.erb
│ │ │ ├── _outline.html.erb
│ │ │ ├── _sizes.html.erb
│ │ │ └── index.html.erb
│ │ │ ├── forms
│ │ │ └── index.html.erb
│ │ │ ├── grid
│ │ │ └── index.html.erb
│ │ │ ├── icons
│ │ │ └── index.html.erb
│ │ │ ├── media
│ │ │ └── index.html.erb
│ │ │ ├── miscellaneous
│ │ │ ├── _avatars.html.erb
│ │ │ ├── _badges.html.erb
│ │ │ ├── _cards.html.erb
│ │ │ ├── _modals.html.erb
│ │ │ ├── _progress.html.erb
│ │ │ ├── _tabs_example.html.erb
│ │ │ ├── _tags.html.erb
│ │ │ ├── _timestamps.html.erb
│ │ │ ├── _tooltips.html.erb
│ │ │ ├── index.html.erb
│ │ │ ├── modal.html.erb
│ │ │ └── modal_post.html.erb
│ │ │ ├── theme
│ │ │ ├── _accordion.html.erb
│ │ │ ├── _alerts.html.erb
│ │ │ ├── _backgrounds.html.erb
│ │ │ ├── _badges.html.erb
│ │ │ ├── _buttons.html.erb
│ │ │ ├── _fields.html.erb
│ │ │ ├── _modal.html.erb
│ │ │ ├── _table.html.erb
│ │ │ ├── _typography.html.erb
│ │ │ └── index.html.erb
│ │ │ └── typography
│ │ │ ├── _blockquotes.html.erb
│ │ │ ├── _code.html.erb
│ │ │ ├── _colors.html.erb
│ │ │ ├── _headings.html.erb
│ │ │ ├── _inline.html.erb
│ │ │ ├── _lists.html.erb
│ │ │ └── index.html.erb
│ │ └── layouts
│ │ ├── application.html.erb
│ │ ├── mailer.html.erb
│ │ └── mailer.text.erb
├── bin
│ ├── bundle
│ ├── rails
│ ├── rake
│ ├── setup
│ └── update
├── config.ru
├── config
│ ├── application.rb
│ ├── boot.rb
│ ├── cable.yml
│ ├── database.yml
│ ├── environment.rb
│ ├── environments
│ │ ├── development.rb
│ │ ├── production.rb
│ │ └── test.rb
│ ├── initializers
│ │ ├── application_controller_renderer.rb
│ │ ├── assets.rb
│ │ ├── backtrace_silencers.rb
│ │ ├── cookies_serializer.rb
│ │ ├── filter_parameter_logging.rb
│ │ ├── inflections.rb
│ │ ├── mime_types.rb
│ │ ├── session_store.rb
│ │ ├── trestle.rb
│ │ └── wrap_parameters.rb
│ ├── locales
│ │ └── en.yml
│ ├── puma.rb
│ ├── routes.rb
│ ├── secrets.yml
│ └── spring.rb
├── db
│ ├── migrate
│ │ ├── 20210712064032_create_offices.rb
│ │ ├── 20210712071021_create_users.rb
│ │ ├── 20210712104832_create_categories.rb
│ │ ├── 20210713021857_create_articles.rb
│ │ └── 20210714014917_create_articles_categories.rb
│ ├── schema.rb
│ └── seeds.rb
├── lib
│ └── assets
│ │ └── .keep
├── log
│ └── .keep
└── public
│ ├── 404.html
│ ├── 422.html
│ ├── 500.html
│ ├── apple-touch-icon-precomposed.png
│ ├── apple-touch-icon.png
│ └── favicon.ico
├── spec
├── dummy
│ ├── Rakefile
│ ├── app
│ │ ├── admin
│ │ │ ├── automatic_admin.rb
│ │ │ ├── modal_admin.rb
│ │ │ ├── posts_admin.rb
│ │ │ ├── scopes_admin.rb
│ │ │ └── singular_post_admin.rb
│ │ ├── assets
│ │ │ ├── config
│ │ │ │ └── manifest.js
│ │ │ ├── images
│ │ │ │ └── .keep
│ │ │ ├── javascripts
│ │ │ │ ├── application.js
│ │ │ │ └── trestle
│ │ │ │ │ └── custom.js
│ │ │ └── stylesheets
│ │ │ │ ├── application.css
│ │ │ │ └── trestle
│ │ │ │ └── _custom.css
│ │ ├── controllers
│ │ │ ├── application_controller.rb
│ │ │ └── concerns
│ │ │ │ └── .keep
│ │ ├── helpers
│ │ │ └── application_helper.rb
│ │ ├── models
│ │ │ ├── application_record.rb
│ │ │ ├── concerns
│ │ │ │ └── .keep
│ │ │ └── post.rb
│ │ └── views
│ │ │ └── layouts
│ │ │ ├── application.html.erb
│ │ │ ├── mailer.html.erb
│ │ │ └── mailer.text.erb
│ ├── bin
│ │ ├── bundle
│ │ ├── rails
│ │ ├── rake
│ │ ├── setup
│ │ └── update
│ ├── config.ru
│ ├── config
│ │ ├── application.rb
│ │ ├── boot.rb
│ │ ├── cable.yml
│ │ ├── database.yml
│ │ ├── environment.rb
│ │ ├── environments
│ │ │ ├── development.rb
│ │ │ ├── production.rb
│ │ │ └── test.rb
│ │ ├── initializers
│ │ │ ├── application_controller_renderer.rb
│ │ │ ├── assets.rb
│ │ │ ├── backtrace_silencers.rb
│ │ │ ├── cookies_serializer.rb
│ │ │ ├── filter_parameter_logging.rb
│ │ │ ├── inflections.rb
│ │ │ ├── mime_types.rb
│ │ │ ├── session_store.rb
│ │ │ ├── trestle.rb
│ │ │ └── wrap_parameters.rb
│ │ ├── locales
│ │ │ └── en.yml
│ │ ├── puma.rb
│ │ ├── routes.rb
│ │ ├── secrets.yml
│ │ └── spring.rb
│ ├── db
│ │ ├── migrate
│ │ │ └── 20170915062615_create_posts.rb
│ │ └── schema.rb
│ ├── lib
│ │ └── assets
│ │ │ └── .keep
│ ├── log
│ │ └── .keep
│ ├── public
│ │ ├── 404.html
│ │ ├── 422.html
│ │ ├── 500.html
│ │ ├── apple-touch-icon-precomposed.png
│ │ ├── apple-touch-icon.png
│ │ └── favicon.ico
│ └── tmp
│ │ └── .keep
├── feature
│ ├── automatic_resource_spec.rb
│ ├── modal_form_spec.rb
│ ├── resource_spec.rb
│ ├── scopes_spec.rb
│ ├── shakedown_spec.rb
│ └── singular_resource_spec.rb
├── generators
│ ├── admin_generator_spec.rb
│ └── resource_generator_spec.rb
├── integration
│ ├── resource_controller_spec.rb
│ └── routes_spec.rb
├── spec_helper.rb
├── support
│ ├── capybara.rb
│ ├── contexts
│ │ ├── countries.rb
│ │ ├── form.rb
│ │ └── template.rb
│ ├── feature_helper.rb
│ ├── i18n_helper.rb
│ └── matchers
│ │ └── have_accessor.rb
└── trestle
│ ├── admin
│ └── builder_spec.rb
│ ├── admin_spec.rb
│ ├── attribute_spec.rb
│ ├── breadcrumb_spec.rb
│ ├── color_spec.rb
│ ├── configurable_spec.rb
│ ├── configuration_spec.rb
│ ├── debug_errors_spec.rb
│ ├── display_spec.rb
│ ├── evaluation_context_spec.rb
│ ├── form
│ ├── builder_spec.rb
│ ├── fields
│ │ ├── check_box_spec.rb
│ │ ├── collection_check_boxes_spec.rb
│ │ ├── collection_radio_buttons_spec.rb
│ │ ├── collection_select_spec.rb
│ │ ├── color_field_spec.rb
│ │ ├── date_field_spec.rb
│ │ ├── date_picker_examples.rb
│ │ ├── date_select_spec.rb
│ │ ├── datetime_field_spec.rb
│ │ ├── datetime_select_spec.rb
│ │ ├── email_field_spec.rb
│ │ ├── file_field_spec.rb
│ │ ├── form_control_examples.rb
│ │ ├── form_field_examples.rb
│ │ ├── form_group_spec.rb
│ │ ├── grouped_collection_select_spec.rb
│ │ ├── month_field_spec.rb
│ │ ├── number_field_spec.rb
│ │ ├── password_field_spec.rb
│ │ ├── radio_button_spec.rb
│ │ ├── range_field_spec.rb
│ │ ├── search_field_spec.rb
│ │ ├── select_spec.rb
│ │ ├── static_field_spec.rb
│ │ ├── tag_select_spec.rb
│ │ ├── telephone_field.rb
│ │ ├── text_area_spec.rb
│ │ ├── text_field_spec.rb
│ │ ├── time_field_spec.rb
│ │ ├── time_select_spec.rb
│ │ ├── time_zone_select_spec.rb
│ │ ├── url_field_spec.rb
│ │ └── week_field_spec.rb
│ └── renderer_spec.rb
│ ├── form_spec.rb
│ ├── helpers
│ ├── avatar_helper_spec.rb
│ ├── card_helper_spec.rb
│ ├── container_helper_spec.rb
│ ├── form_helper_spec.rb
│ ├── format_helper_spec.rb
│ ├── gravatar_helper_spec.rb
│ ├── grid_helper_spec.rb
│ ├── hook_helper_spec.rb
│ ├── i18n_helper_spec.rb
│ ├── icon_helper_spec.rb
│ ├── modal_helper_spec.rb
│ ├── navigation_helper_spec.rb
│ ├── params_helper_spec.rb
│ ├── sort_helper_spec.rb
│ ├── status_helper_spec.rb
│ ├── table_helper_spec.rb
│ ├── timestamp_helper_spec.rb
│ ├── title_helper_spec.rb
│ └── url_helper_spec.rb
│ ├── hook_spec.rb
│ ├── model_name_spec.rb
│ ├── navigation
│ ├── block_spec.rb
│ ├── group_spec.rb
│ └── item_spec.rb
│ ├── navigation_spec.rb
│ ├── options_spec.rb
│ ├── registry_spec.rb
│ ├── resource
│ ├── builder_spec.rb
│ └── toolbar_spec.rb
│ ├── resource_spec.rb
│ ├── scopes
│ ├── block_spec.rb
│ └── scope_spec.rb
│ ├── scopes_spec.rb
│ ├── tab_spec.rb
│ ├── table
│ ├── actions_column_spec.rb
│ ├── builder_spec.rb
│ ├── column_spec.rb
│ └── select_column_spec.rb
│ ├── table_spec.rb
│ ├── toolbar
│ └── item_spec.rb
│ ├── toolbar_spec.rb
│ └── trestle_spec.rb
├── trestle.gemspec
├── webpack.config.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["@babel/preset-env"]
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 0.25%
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | app/assets/bundle/**/* -diff
2 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Publish gem
2 |
3 | on: workflow_dispatch
4 |
5 | jobs:
6 | push:
7 | runs-on: ubuntu-latest
8 |
9 | permissions:
10 | contents: write
11 | id-token: write
12 |
13 | # If you configured a GitHub environment on RubyGems, you must use it here.
14 | environment: release
15 |
16 | steps:
17 | # Set up
18 | - uses: actions/checkout@v4
19 | - name: Set up Ruby
20 | uses: ruby/setup-ruby@v1
21 | with:
22 | bundler-cache: true
23 | ruby-version: ruby
24 |
25 | # Release
26 | - uses: rubygems/release-gem@v1
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.bundle/
2 | /.yardoc
3 | /Gemfile.lock
4 | /gemfiles/*.lock
5 | /_yardoc/
6 | /coverage/
7 | /doc/
8 | /pkg/
9 | /spec/reports/
10 | /tmp/
11 | /sandbox/db/*.sqlite3
12 | /sandbox/db/*.sqlite3-shm
13 | /sandbox/db/*.sqlite3-wal
14 | /sandbox/*.sqlite3-journal
15 | /sandbox/log/*.log
16 | /sandbox/tmp/
17 | /spec/dummy/db/*.sqlite3
18 | /spec/dummy/db/*.sqlite3-shm
19 | /spec/dummy/db/*.sqlite3-wal
20 | /spec/dummy/*.sqlite3-journal
21 | /spec/dummy/log/*.log
22 | /spec/dummy/tmp/*
23 | /spec/dummy/config/credentials.yml.enc
24 | /spec/dummy/config/master.key
25 | /spec/dummy/public/assets/
26 | /node_modules
27 | /i18n/locale/*.json
28 | *.sqlite3-shm
29 | *.sqlite3-wal
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --format documentation
2 | --color
3 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | group :development do
4 | gem 'bcrypt'
5 | gem 'faker'
6 | end
7 |
8 | group :test do
9 | gem 'coveralls_reborn', require: false
10 | gem 'guard-rspec', require: false
11 |
12 | gem 'capybara'
13 | gem 'selenium-webdriver'
14 | gem 'puma'
15 | gem 'launchy'
16 | gem 'capybara-screenshot'
17 | end
18 |
19 | # gem 'rails', '~> 6.0.0'
20 | # gem 'rails', '~> 6.1.0'
21 | # gem 'rails', '~> 7.0.0'
22 | # gem 'rails', '~> 7.1.0'
23 | gem 'rails', '~> 7.2.0'
24 | # gem 'rails', '~> 8.0.0'
25 |
26 | gem 'haml'
27 | gem 'sqlite3'
28 |
29 | gem 'sprockets-rails'
30 | # gem 'sassc-rails'
31 | # gem 'propshaft'
32 |
33 | gem 'i18n-js'
34 |
35 | # Specify your gem's dependencies in trestle.gemspec
36 | gemspec
37 |
38 | gem "rake", "~> 13.0"
39 |
--------------------------------------------------------------------------------
/Guardfile:
--------------------------------------------------------------------------------
1 | guard :rspec, cmd: "bundle exec rspec", all_on_start: true, all_after_pass: true do
2 | require "guard/rspec/dsl"
3 | dsl = Guard::RSpec::Dsl.new(self)
4 |
5 | # RSpec files
6 | rspec = dsl.rspec
7 | watch(rspec.spec_helper) { rspec.spec_dir }
8 | watch(rspec.spec_support) { rspec.spec_dir }
9 | watch(rspec.spec_files)
10 |
11 | # Ruby files
12 | ruby = dsl.ruby
13 | dsl.watch_spec_files_for(ruby.lib_files)
14 |
15 | # Rails files
16 | rails = dsl.rails(view_extensions: %w(erb))
17 | dsl.watch_spec_files_for(rails.app_files)
18 | dsl.watch_spec_files_for(rails.views)
19 | end
20 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require "bundler/gem_tasks"
2 | require "rspec/core/rake_task"
3 |
4 | RSpec::Core::RakeTask.new(:spec)
5 |
6 | task :default => :spec
7 |
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrestleAdmin/trestle/020161aec0c6923f218cbf7552cc677f77204a43/app/assets/bundle/trestle/fa-brands-400.ttf
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrestleAdmin/trestle/020161aec0c6923f218cbf7552cc677f77204a43/app/assets/bundle/trestle/fa-brands-400.woff2
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrestleAdmin/trestle/020161aec0c6923f218cbf7552cc677f77204a43/app/assets/bundle/trestle/fa-regular-400.ttf
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrestleAdmin/trestle/020161aec0c6923f218cbf7552cc677f77204a43/app/assets/bundle/trestle/fa-regular-400.woff2
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrestleAdmin/trestle/020161aec0c6923f218cbf7552cc677f77204a43/app/assets/bundle/trestle/fa-solid-900.ttf
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrestleAdmin/trestle/020161aec0c6923f218cbf7552cc677f77204a43/app/assets/bundle/trestle/fa-solid-900.woff2
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/bg.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).bg={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],longhand:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота"]},months:{shorthand:["Яну","Фев","Март","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Ное","Дек"],longhand:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"]},time_24hr:!0,firstDayOfWeek:1};n.l10ns.bg=o;var t=n.l10ns;e.Bulgarian=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/bn.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).bn={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],longhand:["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"]},months:{shorthand:["জানু","ফেব্রু","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগ","সেপ্টে","অক্টো","নভে","ডিসে"],longhand:["জানুয়ারী","ফেব্রুয়ারী","মার্চ","এপ্রিল","মে","জুন","জুলাই","আগস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"]}};n.l10ns.bn=o;var d=n.l10ns;e.Bangla=o,e.default=d,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/bs.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).bs={})}(this,(function(e){"use strict";var t="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},n={firstDayOfWeek:1,weekdays:{shorthand:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],longhand:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"]},months:{shorthand:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],longhand:["Januar","Februar","Mart","April","Maj","Juni","Juli","Avgust","Septembar","Oktobar","Novembar","Decembar"]},time_24hr:!0};t.l10ns.bs=n;var a=t.l10ns;e.Bosnian=n,e.default=a,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/da.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).da={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},a={weekdays:{shorthand:["søn","man","tir","ons","tors","fre","lør"],longhand:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"]},months:{shorthand:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],longhand:["januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december"]},ordinal:function(){return"."},firstDayOfWeek:1,rangeSeparator:" til ",weekAbbreviation:"uge",time_24hr:!0};n.l10ns.da=a;var r=n.l10ns;e.Danish=a,e.default=r,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/es.js:
--------------------------------------------------------------------------------
1 | !function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o(exports):"function"==typeof define&&define.amd?define(["exports"],o):o((e="undefined"!=typeof globalThis?globalThis:e||self).es={})}(this,(function(e){"use strict";var o="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},n={weekdays:{shorthand:["Dom","Lun","Mar","Mié","Jue","Vie","Sáb"],longhand:["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"]},months:{shorthand:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],longhand:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"]},ordinal:function(){return"º"},firstDayOfWeek:1,rangeSeparator:" a ",time_24hr:!0};o.l10ns.es=n;var i=o.l10ns;e.Spanish=n,e.default=i,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/fa.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).fa={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["یک","دو","سه","چهار","پنج","جمعه","شنبه"],longhand:["یکشنبه","دوشنبه","سهشنبه","چهارشنبه","پنچشنبه","جمعه","شنبه"]},months:{shorthand:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],longhand:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"]},firstDayOfWeek:6,ordinal:function(){return""}};n.l10ns.fa=o;var t=n.l10ns;e.Persian=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/fi.js:
--------------------------------------------------------------------------------
1 | !function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).fi={})}(this,(function(e){"use strict";var i="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},u={firstDayOfWeek:1,weekdays:{shorthand:["su","ma","ti","ke","to","pe","la"],longhand:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai"]},months:{shorthand:["tammi","helmi","maalis","huhti","touko","kesä","heinä","elo","syys","loka","marras","joulu"],longhand:["tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu"]},ordinal:function(){return"."},time_24hr:!0};i.l10ns.fi=u;var n=i.l10ns;e.Finnish=u,e.default=n,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/ga.js:
--------------------------------------------------------------------------------
1 | !function(e,a){"object"==typeof exports&&"undefined"!=typeof module?a(exports):"function"==typeof define&&define.amd?define(["exports"],a):a((e="undefined"!=typeof globalThis?globalThis:e||self).ga={})}(this,(function(e){"use strict";var a="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},i={firstDayOfWeek:1,weekdays:{shorthand:["Dom","Lua","Mái","Céa","Déa","Aoi","Sat"],longhand:["Dé Domhnaigh","Dé Luain","Dé Máirt","Dé Céadaoin","Déardaoin","Dé hAoine","Dé Sathairn"]},months:{shorthand:["Ean","Fea","Már","Aib","Bea","Mei","Iúi","Lún","MFo","DFo","Sam","Nol"],longhand:["Eanáir","Feabhra","Márta","Aibreán","Bealtaine","Meitheamh","Iúil","Lúnasa","Meán Fómhair","Deireadh Fómhair","Samhain","Nollaig"]},time_24hr:!0};a.l10ns.hr=i;var n=a.l10ns;e.Irish=i,e.default=n,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/he.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).he={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["א","ב","ג","ד","ה","ו","ש"],longhand:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת"]},months:{shorthand:["ינו׳","פבר׳","מרץ","אפר׳","מאי","יוני","יולי","אוג׳","ספט׳","אוק׳","נוב׳","דצמ׳"],longhand:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"]},rangeSeparator:" אל ",time_24hr:!0};n.l10ns.he=o;var t=n.l10ns;e.Hebrew=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/hi.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).hi={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["रवि","सोम","मंगल","बुध","गुरु","शुक्र","शनि"],longhand:["रविवार","सोमवार","मंगलवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"]},months:{shorthand:["जन","फर","मार्च","अप्रेल","मई","जून","जूलाई","अग","सित","अक्ट","नव","दि"],longhand:["जनवरी ","फरवरी","मार्च","अप्रेल","मई","जून","जूलाई","अगस्त ","सितम्बर","अक्टूबर","नवम्बर","दिसम्बर"]}};n.l10ns.hi=o;var d=n.l10ns;e.Hindi=o,e.default=d,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/hr.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).hr={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={firstDayOfWeek:1,weekdays:{shorthand:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],longhand:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"]},months:{shorthand:["Sij","Velj","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro"],longhand:["Siječanj","Veljača","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac"]},time_24hr:!0};n.l10ns.hr=o;var a=n.l10ns;e.Croatian=o,e.default=a,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/id.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).id={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},i={weekdays:{shorthand:["Min","Sen","Sel","Rab","Kam","Jum","Sab"],longhand:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"]},months:{shorthand:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des"],longhand:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"]},firstDayOfWeek:1,ordinal:function(){return""},time_24hr:!0,rangeSeparator:" - "};n.l10ns.id=i;var a=n.l10ns;e.Indonesian=i,e.default=a,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/ja.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).ja={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},a={weekdays:{shorthand:["日","月","火","水","木","金","土"],longhand:["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"]},months:{shorthand:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],longhand:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"]},time_24hr:!0,rangeSeparator:" から ",monthAriaLabel:"月",amPM:["午前","午後"],yearAriaLabel:"年",hourAriaLabel:"時間",minuteAriaLabel:"分"};n.l10ns.ja=a;var o=n.l10ns;e.Japanese=a,e.default=o,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/ko.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).ko={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["일","월","화","수","목","금","토"],longhand:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"]},months:{shorthand:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],longhand:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"]},ordinal:function(){return"일"},rangeSeparator:" ~ ",amPM:["오전","오후"]};n.l10ns.ko=o;var t=n.l10ns;e.Korean=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/lv.js:
--------------------------------------------------------------------------------
1 | !function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).lv={})}(this,(function(e){"use strict";var i="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},n={firstDayOfWeek:1,weekdays:{shorthand:["Sv","Pr","Ot","Tr","Ce","Pk","Se"],longhand:["Svētdiena","Pirmdiena","Otrdiena","Trešdiena","Ceturtdiena","Piektdiena","Sestdiena"]},months:{shorthand:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],longhand:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"]},rangeSeparator:" līdz ",time_24hr:!0};i.l10ns.lv=n;var t=i.l10ns;e.Latvian=n,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/mk.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).mk={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["Не","По","Вт","Ср","Че","Пе","Са"],longhand:["Недела","Понеделник","Вторник","Среда","Четврток","Петок","Сабота"]},months:{shorthand:["Јан","Фев","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Ное","Дек"],longhand:["Јануари","Февруари","Март","Април","Мај","Јуни","Јули","Август","Септември","Октомври","Ноември","Декември"]},firstDayOfWeek:1,weekAbbreviation:"Нед.",rangeSeparator:" до ",time_24hr:!0};n.l10ns.mk=o;var t=n.l10ns;e.Macedonian=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/ms.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).ms={})}(this,(function(e){"use strict";var n=("undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}}).l10ns;e.Malaysian={weekdays:{shorthand:["Aha","Isn","Sel","Rab","Kha","Jum","Sab"],longhand:["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"]},months:{shorthand:["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogo","Sep","Okt","Nov","Dis"],longhand:["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"]},firstDayOfWeek:1,ordinal:function(){return""}},e.default=n,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/my.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).my={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["နွေ","လာ","ဂါ","ဟူး","ကြာ","သော","နေ"],longhand:["တနင်္ဂနွေ","တနင်္လာ","အင်္ဂါ","ဗုဒ္ဓဟူး","ကြာသပတေး","သောကြာ","စနေ"]},months:{shorthand:["ဇန်","ဖေ","မတ်","ပြီ","မေ","ဇွန်","လိုင်","သြ","စက်","အောက်","နို","ဒီ"],longhand:["ဇန်နဝါရီ","ဖေဖော်ဝါရီ","မတ်","ဧပြီ","မေ","ဇွန်","ဇူလိုင်","သြဂုတ်","စက်တင်ဘာ","အောက်တိုဘာ","နိုဝင်ဘာ","ဒီဇင်ဘာ"]},firstDayOfWeek:1,ordinal:function(){return""},time_24hr:!0};n.l10ns.my=o;var t=n.l10ns;e.Burmese=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/pa.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).pa={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["ਐਤ","ਸੋਮ","ਮੰਗਲ","ਬੁੱਧ","ਵੀਰ","ਸ਼ੁੱਕਰ","ਸ਼ਨਿੱਚਰ"],longhand:["ਐਤਵਾਰ","ਸੋਮਵਾਰ","ਮੰਗਲਵਾਰ","ਬੁੱਧਵਾਰ","ਵੀਰਵਾਰ","ਸ਼ੁੱਕਰਵਾਰ","ਸ਼ਨਿੱਚਰਵਾਰ"]},months:{shorthand:["ਜਨ","ਫ਼ਰ","ਮਾਰ","ਅਪ੍ਰੈ","ਮਈ","ਜੂਨ","ਜੁਲਾ","ਅਗ","ਸਤੰ","ਅਕ","ਨਵੰ","ਦਸੰ"],longhand:["ਜਨਵਰੀ","ਫ਼ਰਵਰੀ","ਮਾਰਚ","ਅਪ੍ਰੈਲ","ਮਈ","ਜੂਨ","ਜੁਲਾਈ","ਅਗਸਤ","ਸਤੰਬਰ","ਅਕਤੂਬਰ","ਨਵੰਬਰ","ਦਸੰਬਰ"]},time_24hr:!0};n.l10ns.pa=o;var t=n.l10ns;e.Punjabi=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/pt.js:
--------------------------------------------------------------------------------
1 | !function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o(exports):"function"==typeof define&&define.amd?define(["exports"],o):o((e="undefined"!=typeof globalThis?globalThis:e||self).pt={})}(this,(function(e){"use strict";var o="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},a={weekdays:{shorthand:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],longhand:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"]},months:{shorthand:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],longhand:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"]},rangeSeparator:" até ",time_24hr:!0};o.l10ns.pt=a;var n=o.l10ns;e.Portuguese=a,e.default=n,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/ro.js:
--------------------------------------------------------------------------------
1 | !function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).ro={})}(this,(function(e){"use strict";var i="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},n={weekdays:{shorthand:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm"],longhand:["Duminică","Luni","Marți","Miercuri","Joi","Vineri","Sâmbătă"]},months:{shorthand:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Noi","Dec"],longhand:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"]},firstDayOfWeek:1,time_24hr:!0,ordinal:function(){return""}};i.l10ns.ro=n;var o=i.l10ns;e.Romanian=n,e.default=o,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/si.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).si={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["ඉ","ස","අ","බ","බ්ර","සි","සෙ"],longhand:["ඉරිදා","සඳුදා","අඟහරුවාදා","බදාදා","බ්රහස්පතින්දා","සිකුරාදා","සෙනසුරාදා"]},months:{shorthand:["ජන","පෙබ","මාර්","අප්රේ","මැයි","ජුනි","ජූලි","අගෝ","සැප්","ඔක්","නොවැ","දෙසැ"],longhand:["ජනවාරි","පෙබරවාරි","මාර්තු","අප්රේල්","මැයි","ජුනි","ජූලි","අගෝස්තු","සැප්තැම්බර්","ඔක්තෝබර්","නොවැම්බර්","දෙසැම්බර්"]},time_24hr:!0};n.l10ns.si=o;var i=n.l10ns;e.Sinhala=o,e.default=i,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/sk.js:
--------------------------------------------------------------------------------
1 | !function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o(exports):"function"==typeof define&&define.amd?define(["exports"],o):o((e="undefined"!=typeof globalThis?globalThis:e||self).sk={})}(this,(function(e){"use strict";var o="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},t={weekdays:{shorthand:["Ned","Pon","Ut","Str","Štv","Pia","Sob"],longhand:["Nedeľa","Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota"]},months:{shorthand:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],longhand:["Január","Február","Marec","Apríl","Máj","Jún","Júl","August","September","Október","November","December"]},firstDayOfWeek:1,rangeSeparator:" do ",time_24hr:!0,ordinal:function(){return"."}};o.l10ns.sk=t;var n=o.l10ns;e.Slovak=t,e.default=n,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/sl.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).sl={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["Ned","Pon","Tor","Sre","Čet","Pet","Sob"],longhand:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota"]},months:{shorthand:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],longhand:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"]},firstDayOfWeek:1,rangeSeparator:" do ",time_24hr:!0,ordinal:function(){return"."}};n.l10ns.sl=o;var t=n.l10ns;e.Slovenian=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/sr-cyr.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self)["sr-cyr"]={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],longhand:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"]},months:{shorthand:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],longhand:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"]},firstDayOfWeek:1,weekAbbreviation:"Нед.",rangeSeparator:" до "};n.l10ns.sr=o;var i=n.l10ns;e.SerbianCyrillic=o,e.default=i,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/sr.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).sr={})}(this,(function(e){"use strict";var t="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},a={weekdays:{shorthand:["Ned","Pon","Uto","Sre","Čet","Pet","Sub"],longhand:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota"]},months:{shorthand:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],longhand:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"]},firstDayOfWeek:1,weekAbbreviation:"Ned.",rangeSeparator:" do ",time_24hr:!0};t.l10ns.sr=a;var n=t.l10ns;e.Serbian=a,e.default=n,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/sv.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).sv={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},a={firstDayOfWeek:1,weekAbbreviation:"v",weekdays:{shorthand:["sön","mån","tis","ons","tor","fre","lör"],longhand:["söndag","måndag","tisdag","onsdag","torsdag","fredag","lördag"]},months:{shorthand:["jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec"],longhand:["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"]},rangeSeparator:" till ",time_24hr:!0,ordinal:function(){return"."}};n.l10ns.sv=a;var o=n.l10ns;e.Swedish=a,e.default=o,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/uk.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).uk={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={firstDayOfWeek:1,weekdays:{shorthand:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],longhand:["Неділя","Понеділок","Вівторок","Середа","Четвер","П'ятниця","Субота"]},months:{shorthand:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],longhand:["Січень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"]},time_24hr:!0};n.l10ns.uk=o;var t=n.l10ns;e.Ukrainian=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/vn.js:
--------------------------------------------------------------------------------
1 | !function(n,h){"object"==typeof exports&&"undefined"!=typeof module?h(exports):"function"==typeof define&&define.amd?define(["exports"],h):h((n="undefined"!=typeof globalThis?globalThis:n||self).vn={})}(this,(function(n){"use strict";var h="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},e={weekdays:{shorthand:["CN","T2","T3","T4","T5","T6","T7"],longhand:["Chủ nhật","Thứ hai","Thứ ba","Thứ tư","Thứ năm","Thứ sáu","Thứ bảy"]},months:{shorthand:["Th1","Th2","Th3","Th4","Th5","Th6","Th7","Th8","Th9","Th10","Th11","Th12"],longhand:["Tháng một","Tháng hai","Tháng ba","Tháng tư","Tháng năm","Tháng sáu","Tháng bảy","Tháng tám","Tháng chín","Tháng mười","Tháng mười một","Tháng mười hai"]},firstDayOfWeek:1,rangeSeparator:" đến "};h.l10ns.vn=e;var T=h.l10ns;n.Vietnamese=e,n.default=T,Object.defineProperty(n,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/zh-tw.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self)["zh-tw"]={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["週日","週一","週二","週三","週四","週五","週六"],longhand:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"]},months:{shorthand:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],longhand:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},rangeSeparator:" 至 ",weekAbbreviation:"週",scrollTitle:"滾動切換",toggleTitle:"點擊切換 12/24 小時時制"};n.l10ns.zh_tw=o;var t=n.l10ns;e.MandarinTraditional=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/bundle/trestle/locale/flatpickr/zh.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).zh={})}(this,(function(e){"use strict";var n="undefined"!=typeof window&&void 0!==window.flatpickr?window.flatpickr:{l10ns:{}},o={weekdays:{shorthand:["周日","周一","周二","周三","周四","周五","周六"],longhand:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"]},months:{shorthand:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],longhand:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},rangeSeparator:" 至 ",weekAbbreviation:"周",scrollTitle:"滚动切换",toggleTitle:"点击切换 12/24 小时时制"};n.l10ns.zh=o;var t=n.l10ns;e.Mandarin=o,e.default=t,Object.defineProperty(e,"__esModule",{value:!0})}));
--------------------------------------------------------------------------------
/app/assets/javascripts/trestle/custom.js:
--------------------------------------------------------------------------------
1 | // This file is left as an extension point for user customization.
2 | //
3 | // It will be overridden by the similarly named file within
4 | // the app/assets folder of the Rails application.
5 |
--------------------------------------------------------------------------------
/app/assets/sprockets/trestle/_custom.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is left as an extension point for user customization.
3 | *
4 | * It will be overridden by the similarly named file within
5 | * the app/assets folder of the Rails application.
6 | */
7 |
--------------------------------------------------------------------------------
/app/assets/sprockets/trestle/custom.css:
--------------------------------------------------------------------------------
1 | //= require trestle/_custom
--------------------------------------------------------------------------------
/app/assets/sprockets/trestle/manifest.js:
--------------------------------------------------------------------------------
1 | //= link_tree ../../bundle
2 | //= link trestle/custom.js
3 | //= link trestle/custom.css
4 | //= link trestle/icons/font-awesome.css
--------------------------------------------------------------------------------
/app/assets/stylesheets/trestle/custom.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is left as an extension point for user customization.
3 | *
4 | * It will be overridden by the similarly named file within
5 | * the app/assets folder of the Rails application.
6 | */
7 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/controller/breadcrumbs.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Controller
3 | module Breadcrumbs
4 | extend ActiveSupport::Concern
5 |
6 | included do
7 | helper_method :breadcrumbs
8 | helper_method :breadcrumb
9 | end
10 |
11 | protected
12 | def breadcrumbs
13 | @_breadcrumbs ||= Breadcrumb::Trail.new(Trestle.config.root_breadcrumbs)
14 | end
15 |
16 | def breadcrumb(label, path=nil)
17 | breadcrumbs.append(label, path)
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/controller/callbacks.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Controller
3 | module Callbacks
4 | extend ActiveSupport::Concern
5 |
6 | included do
7 | Trestle.config.before_actions.each do |action|
8 | before_action(action.options, &action.block)
9 | end
10 |
11 | Trestle.config.after_actions.each do |action|
12 | after_action(action.options, &action.block)
13 | end
14 |
15 | Trestle.config.around_actions.each do |action|
16 | around_action(action.options, &action.block)
17 | end
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/controller/helpers.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Controller
3 | module Helpers
4 | extend ActiveSupport::Concern
5 |
6 | include Trestle::FlashHelper
7 |
8 | included do
9 | # Allow inclusion of helpers from Rails application
10 | self.helpers_path += Rails.application.helpers_paths
11 |
12 | # Add helpers declared from configuration as blocks
13 | helper Trestle.config.helper_module
14 |
15 | # Add helpers declared from configuration as module references
16 | helper *Trestle.config.helpers
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/controller/layout.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Controller
3 | module Layout
4 | extend ActiveSupport::Concern
5 |
6 | included do
7 | layout :choose_layout
8 | end
9 |
10 | protected
11 | def choose_layout
12 | request.xhr? ? false : "trestle/admin"
13 | end
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/controller/location.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Controller
3 | module Location
4 | extend ActiveSupport::Concern
5 |
6 | included do
7 | after_action :set_trestle_location_header
8 | end
9 |
10 | # The X-Trestle-Location header is set to indicate that the remote form has triggered
11 | # a new page URL (e.g. new -> show) without demanding a full page refresh.
12 | def set_trestle_location_header
13 | unless modal_request? || response.location
14 | headers["X-Trestle-Location"] = request.path
15 | end
16 | end
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/controller/modal.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Controller
3 | module Modal
4 | extend ActiveSupport::Concern
5 |
6 | include Trestle::ModalHelper
7 |
8 | included do
9 | helper_method :modal_request?, :dialog_request?
10 | end
11 |
12 | protected
13 | def modal_request?
14 | turbo_frame_request_id == "modal" ||
15 | request.headers["X-Trestle-Modal"] ||
16 | request.headers["X-Trestle-Dialog"]
17 | end
18 |
19 | def dialog_request?
20 | Trestle.deprecator.warn("The #dialog_request? helper has been renamed to #modal_request?")
21 | modal_request?
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/controller/title.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Controller
3 | module Title
4 | extend ActiveSupport::Concern
5 |
6 | included do
7 | helper_method :default_title
8 | end
9 |
10 | protected
11 | def title(title=nil)
12 | @_title = title if title
13 | end
14 |
15 | def default_title
16 | @_title || action_name.titleize
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/controller/toolbars.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Controller
3 | module Toolbars
4 | extend ActiveSupport::Concern
5 |
6 | included do
7 | helper_method :toolbars
8 | helper_method :toolbar
9 | end
10 |
11 | protected
12 | def toolbars
13 | @_toolbars ||= {}
14 | end
15 |
16 | def toolbar(name, options={}, &block)
17 | builder = options[:builder] || default_toolbar_builder
18 |
19 | toolbar = (toolbars[name.to_s] ||= Toolbar.new(builder))
20 | toolbar.clear! if options[:clear]
21 | toolbar.append(&block) if block_given?
22 | toolbar
23 | end
24 |
25 | def default_toolbar_builder
26 | Toolbar::Builder
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/controller/turbo_stream.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Controller
3 | module TurboStream
4 | extend ActiveSupport::Concern
5 |
6 | private
7 | def turbo_stream
8 | Trestle::Turbo::TagBuilder.new(view_context)
9 | end
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/resource/controller/redirection.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Resource
3 | module Controller
4 | module Redirection
5 | protected
6 | def redirect_to_return_location(action, instance, status: :found, default: nil, &block)
7 | fallback_location = block_given? ? block : default
8 |
9 | if admin.return_locations[action] && !modal_request?
10 | location = instance_exec(instance, &admin.return_locations[action])
11 |
12 | case location
13 | when :back
14 | redirect_back fallback_location: fallback_location, status: status
15 | else
16 | redirect_to location, status: status
17 | end
18 | else
19 | redirect_to fallback_location, status: status
20 | end
21 | end
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/app/controllers/concerns/trestle/resource/controller/toolbar.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Resource
3 | module Controller
4 | module Toolbar
5 | def default_toolbar_builder
6 | Resource::Toolbar::Builder
7 | end
8 | end
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/controllers/trestle/admin_controller.rb:
--------------------------------------------------------------------------------
1 | class Trestle::AdminController < Trestle::ApplicationController
2 | if respond_to?(:raise_on_missing_callback_actions=)
3 | self.raise_on_missing_callback_actions = false
4 | end
5 |
6 | def index
7 | end
8 |
9 | class << self
10 | attr_reader :admin
11 |
12 | private
13 | def local_prefixes
14 | return admin.view_path_prefixes if admin
15 | [controller_path.sub(/\/$/, "")]
16 | end
17 | end
18 |
19 | def admin
20 | @_admin ||= self.class.admin.new(self)
21 | end
22 | helper_method :admin
23 |
24 | protected
25 | def breadcrumbs
26 | @_breadcrumbs ||= admin.breadcrumbs.dup
27 | end
28 |
29 | def flash_message(type, title:, message:)
30 | {
31 | title: admin.t("flash.#{type}.title", default: title),
32 | message: admin.t("flash.#{type}.message", default: message)
33 | }
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/app/controllers/trestle/application_controller.rb:
--------------------------------------------------------------------------------
1 | class Trestle::ApplicationController < ActionController::Base
2 | protect_from_forgery
3 |
4 | include Trestle::Controller::Breadcrumbs
5 | include Trestle::Controller::Callbacks
6 | include Trestle::Controller::Helpers
7 | include Trestle::Controller::Layout
8 | include Trestle::Controller::Location
9 | include Trestle::Controller::Modal
10 | include Trestle::Controller::Title
11 | include Trestle::Controller::Toolbars
12 | include Trestle::Controller::TurboStream
13 | end
14 |
--------------------------------------------------------------------------------
/app/controllers/trestle/dashboard_controller.rb:
--------------------------------------------------------------------------------
1 | class Trestle::DashboardController < Trestle::ApplicationController
2 | def index
3 | admin = primary_admin
4 | redirect_to admin.path if admin
5 | end
6 |
7 | private
8 | def primary_admin
9 | if navigation = Trestle.navigation(self).first
10 | navigation.admin
11 | elsif Trestle.registry.any?
12 | Trestle.registry.first
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/controllers/trestle/resource_controller.rb:
--------------------------------------------------------------------------------
1 | class Trestle::ResourceController < Trestle::AdminController
2 | include Trestle::Resource::Controller::Actions
3 | include Trestle::Resource::Controller::DataMethods
4 | include Trestle::Resource::Controller::Redirection
5 | include Trestle::Resource::Controller::Toolbar
6 | end
7 |
--------------------------------------------------------------------------------
/app/helpers/trestle/display_helper.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module DisplayHelper
3 | # Returns a plain-text representation of the given model instance,
4 | # typically used when rendering an associated object within a table.
5 | #
6 | # This helper delegates to Trestle::Display, which works by checking the
7 | # existence of each method from `Trestle.config.display_methods` in turn
8 | # and calling the first one it finds.
9 | #
10 | # By default this list is set to:
11 | #
12 | # [:display_name, :full_name, :name, :title, :username, :login, :email]
13 | #
14 | def display(instance)
15 | Trestle::Display.new(instance).to_s
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/helpers/trestle/flash_helper.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | # [Internal]
3 | module FlashHelper
4 | def normalize_flash_alert(flash)
5 | flash.is_a?(Hash) ? flash.with_indifferent_access : { message: flash }
6 | end
7 |
8 | def debug_form_errors?
9 | Trestle.config.debug_form_errors && instance_has_errors?
10 | end
11 |
12 | def instance_has_errors?
13 | instance.errors.any? rescue false
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/helpers/trestle/headings_helper.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module HeadingsHelper
3 | # These methods are delegated to the ActionView::Helpers::TagHelper proxy object for convenience.
4 | delegate :h1, :h2, :h3, :h4, :h5, :h6, to: :tag
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/app/helpers/trestle/hook_helper.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module HookHelper
3 | include Trestle::Hook::Helpers
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/helpers/trestle/icon_helper.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module IconHelper
3 | # Renders an icon (as an tag).
4 | #
5 | # Trestle includes the FontAwesome icon library but other font
6 | # libraries can be included via custom CSS.
7 | #
8 | # classes - List of font name classes to add to the tag
9 | # attributes - Additional HTML attributes to add to the tag
10 | #
11 | # Examples
12 | #
13 | # <%= icon("fas fa-star") %>
14 | # <%= icon("fas", "fa-star", class: "fa-fw text-muted")
15 | #
16 | # Return the HTML i tag for the icon.
17 | def icon(*classes, **attributes)
18 | tag.i("", **attributes.merge(class: [*classes, attributes[:class]]))
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/app/helpers/trestle/layout_helper.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | # [Internal]
3 | module LayoutHelper
4 | SIDEBAR_CLASSES = {
5 | "expanded" => "sidebar-expanded",
6 | "collapsed" => "sidebar-collapsed"
7 | }
8 |
9 | def body_attributes
10 | {
11 | class: body_classes
12 | }.reject { |k, v| v.blank? }
13 | end
14 |
15 | def body_classes
16 | [
17 | SIDEBAR_CLASSES[cookies["trestle:sidebar"]]
18 | ].compact
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/app/helpers/trestle/title_helper.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module TitleHelper
3 | # Returns the page title (if set using content_for), falling back to
4 | # the titleized action name as a default if not set.
5 | def title
6 | content_for(:title) || default_title
7 | end
8 |
9 | def default_title
10 | action_name.titleize
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/helpers/trestle/toolbars_helper.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | # [Internal]
3 | module ToolbarsHelper
4 | def render_toolbar(toolbar, *args)
5 | result = toolbar.groups(self, *args).map do |items|
6 | if items.many?
7 | tag.div(class: "btn-group", role: "group") do
8 | safe_join(items, "\n")
9 | end
10 | else
11 | items.first
12 | end
13 | end
14 |
15 | safe_join(result, "\n")
16 | end
17 |
18 | def deprecated_toolbar(name)
19 | if content_for?(:"#{name}_toolbar")
20 | Trestle.deprecator.warn("Using content_for(:#{name}_toolbar) is deprecated. Please use toolbar(:#{name}) instead.")
21 | content_for(:"#{name}_toolbar")
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/app/helpers/trestle/turbo/stream_helper.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Turbo
3 | module StreamHelper
4 | def turbo_stream
5 | Trestle::Turbo::TagBuilder.new(self)
6 | end
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/helpers/trestle/turbo/tag_builder.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Turbo
3 | class TagBuilder < ::Turbo::Streams::TagBuilder
4 | def modal(template=nil)
5 | turbo_stream_action_tag :modal, template: @view_context.render(template: template || @view_context.action_name, layout: "layouts/trestle/modal", prefixes: @view_context.controller._prefixes, formats: :html)
6 | end
7 |
8 | def close_modal(target)
9 | turbo_stream_action_tag :closeModal, targets: target
10 | end
11 |
12 | def flash
13 | turbo_stream_action_tag :flash, template: @view_context.render(partial: "trestle/flash/flash", formats: :html)
14 | end
15 |
16 | def reload
17 | turbo_stream_action_tag :reload
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/app/views/kaminari/trestle/_first_page.html.erb:
--------------------------------------------------------------------------------
1 | <%# Link to the "First" page
2 | - available local variables
3 | url: url to the first page
4 | current_page: a page object for the currently displayed page
5 | total_pages: total number of pages
6 | per_page: number of items to fetch per page
7 | -%>
8 |
10 | <%= first_page_tag %>
11 | <% each_page do |page| -%>
12 | <% if page.left_outer? || page.right_outer? || page.inside_window? -%>
13 | <%= page_tag page %>
14 | <% elsif !page.was_truncated? -%>
15 | <%= gap_tag %>
16 | <% end -%>
17 | <% end -%>
18 | <%= last_page_tag %>
19 |
20 | <% end -%>
21 |
--------------------------------------------------------------------------------
/app/views/layouts/trestle/modal.html.erb:
--------------------------------------------------------------------------------
1 | <%= tag.div(**modal_wrapper_attributes) do %>
2 | <%= tag.div(**modal_dialog_attributes) do %>
3 | <%= yield %>
4 | <% end %>
5 | <% end %>
6 |
--------------------------------------------------------------------------------
/app/views/trestle/_i18n.html.erb:
--------------------------------------------------------------------------------
1 | <% i18n_fallbacks.each do |locale| %>
2 | <%= javascript_include_tag "trestle/locale/#{locale}", 'data-turbo-track': 'reload' rescue nil %>
3 | <%= javascript_include_tag "trestle/locale/flatpickr/#{flatpickr_locale(locale)}", 'data-turbo-track': 'reload' rescue nil %>
4 | <% end %>
5 |
6 | <%= javascript_tag nonce: true do %>
7 | <% if Trestle.config.javascript_i18n_keys.any? %>
8 | Trestle.i18n.store(<%=raw JSON.pretty_generate(I18n.locale => i18n_javascript_translations) %>);
9 | <% end %>
10 |
11 | Trestle.localize(<%= i18n_fallbacks.map { |l| "'#{l}'" }.join(", ").html_safe %>);
12 | <% end %>
13 |
--------------------------------------------------------------------------------
/app/views/trestle/_theme.html.erb:
--------------------------------------------------------------------------------
1 | <% if Trestle.config.theme.any? %>
2 |
15 | <% end %>
16 |
--------------------------------------------------------------------------------
/app/views/trestle/admin/index.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for(:title, admin.admin_name.titleize) %>
2 |
3 | <%= render layout: "layout" do %>
4 |
<%= t("trestle.onboarding.no_template", path: "app/views/#{admin.view_path}/index.html.erb", default: "To customize this template, please create %{path}
.").html_safe %>
<%= t("trestle.onboarding.no_admins", default: "To begin, please create an admin within app/admin
.").html_safe %>
<%= alert[:message] %>
13 | <% end %> 14 | 15 | <% if local_assigns[:errors] %> 16 | <%= render "trestle/flash/debug", errors: errors %> 17 | <% end %> 18 |<%= t("trestle.onboarding.no_form", default: "Please define a form block or create a _form.html
partial.").html_safe %>
<%= File.join("app/views/admin", class_path, singular_name, "index.html.erb") %>
.
5 | <%% end %>
6 |
--------------------------------------------------------------------------------
/lib/generators/trestle/install/install_generator.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Generators
3 | class InstallGenerator < ::Rails::Generators::Base
4 | desc "Installs Trestle and creates files for configuration and asset customization"
5 |
6 | source_root File.expand_path("../templates", __FILE__)
7 |
8 | def create_initializer
9 | template "trestle.rb.erb", "config/initializers/trestle.rb"
10 | end
11 |
12 | def create_assets
13 | css = (defined?(Sass) || defined?(SassC)) ? "scss" : "css"
14 | template "_custom.#{css}", "app/assets/stylesheets/trestle/_custom.#{css}"
15 | template "custom.js", "app/assets/javascripts/trestle/custom.js"
16 | end
17 |
18 | def create_directory
19 | empty_directory "app/admin"
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/generators/trestle/install/templates/_custom.css:
--------------------------------------------------------------------------------
1 | /* This file may be used for providing additional customizations to the Trestle
2 | * admin. It will be automatically included within all admin pages.
3 | *
4 | * For organizational purposes, you may wish to define your customizations
5 | * within individual partials in this folder and they'll be required below.
6 | *
7 | *= require_tree .
8 | */
9 |
--------------------------------------------------------------------------------
/lib/generators/trestle/install/templates/_custom.scss:
--------------------------------------------------------------------------------
1 | // This file may be used for providing additional customizations to the Trestle
2 | // admin. It will be automatically included within all admin pages.
3 | //
4 | // For organizational purposes, you may wish to define your customizations
5 | // within individual partials and `import` them here, e.g.
6 | //
7 | // @import "trestle/custom/my_custom_css";
8 | //
9 |
--------------------------------------------------------------------------------
/lib/generators/trestle/install/templates/custom.js:
--------------------------------------------------------------------------------
1 | // This file may be used for providing additional customizations to the Trestle
2 | // admin. It will be automatically included within all admin pages.
3 | //
4 | // For organizational purposes, you may wish to define your customizations
5 | // within individual partials and `require` them here.
6 | //
7 | // e.g. //= require "trestle/custom/my_custom_js"
8 |
--------------------------------------------------------------------------------
/lib/trestle/adapters.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Adapters
3 | extend ActiveSupport::Autoload
4 |
5 | require_relative "adapters/adapter"
6 |
7 | autoload :ActiveRecordAdapter
8 | autoload :DraperAdapter
9 | autoload :SequelAdapter
10 |
11 | # Creates a new Adapter class with the given modules mixed in
12 | def self.compose(*modules)
13 | Class.new(Adapter) do
14 | modules.each { |mod| include(mod) }
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/lib/trestle/adapters/draper_adapter.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | module Adapters
3 | module DraperAdapter
4 | def decorate_collection(collection)
5 | if decorator = admin.decorator
6 | decorator.decorate_collection(collection)
7 | else
8 | super
9 | end
10 | end
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/lib/trestle/attribute.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Attribute
3 | attr_reader :name, :type, :options
4 |
5 | def initialize(name, type, options={})
6 | @name, @type, @options = name.to_sym, type, options
7 | end
8 |
9 | def array?
10 | options[:array] == true
11 | end
12 |
13 | class Association < Attribute
14 | def initialize(name, options={})
15 | super(name, :association, options)
16 | end
17 |
18 | def association_name
19 | options[:name] || name.to_s.sub(/_id$/, "")
20 | end
21 |
22 | def association_class
23 | options[:class].respond_to?(:call) ? options[:class].call : options[:class]
24 | end
25 |
26 | def polymorphic?
27 | options[:polymorphic] == true
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/trestle/builder.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Builder
3 | def self.target(name)
4 | attr_reader name
5 | alias_method :target, name
6 | end
7 |
8 | def self.build(*args, &block)
9 | new(*args).build(&block)
10 | end
11 |
12 | def build(&block)
13 | instance_eval(&block) if block_given?
14 | target
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/trestle/debug_errors.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class DebugErrors
3 | def initialize(errors)
4 | @errors = errors
5 | end
6 |
7 | def any?
8 | @errors.any?
9 | end
10 |
11 | def each
12 | if defined?(ActiveModel::Error)
13 | # Rails 6.1 introduces a unified Error class
14 | @errors.each do |error|
15 | yield error.attribute, error.message
16 | end
17 | else
18 | @errors.each do |error, message|
19 | yield error, message
20 | end
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/lib/trestle/display.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Display
3 | def initialize(instance)
4 | @instance = instance
5 | end
6 |
7 | def to_s
8 | if display_method != :to_s || @instance.method(display_method).source_location
9 | @instance.public_send(display_method)
10 | else
11 | "#{@instance.class} (##{@instance.id})"
12 | end
13 | end
14 |
15 | private
16 | def display_method
17 | @display_method ||= Trestle.config.display_methods.find { |m| @instance.respond_to?(m) } || :to_s
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Form
3 | module Fields
4 | require_relative "fields/form_control"
5 | require_relative "fields/form_group"
6 |
7 | require_relative "fields/date_picker"
8 |
9 | require_relative "fields/check_box_helpers"
10 | require_relative "fields/radio_button_helpers"
11 |
12 | Dir.glob("#{__dir__}/fields/*.rb") { |f| require_relative f }
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/check_box_helpers.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Form
3 | module Fields
4 | module CheckBoxHelpers
5 | def switch?
6 | options[:switch]
7 | end
8 |
9 | def inline?
10 | options[:inline]
11 | end
12 |
13 | def default_wrapper_class
14 | [
15 | "form-check",
16 | ("form-switch" if switch?),
17 | ("form-check-inline" if inline?)
18 | ].compact
19 | end
20 |
21 | def input_class
22 | ["form-check-input"]
23 | end
24 |
25 | def label_class
26 | ["form-check-label"]
27 | end
28 |
29 | def defaults
30 | Trestle::Options.new(disabled: readonly?)
31 | end
32 | end
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/color_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::ColorField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_color_field(name, options)
4 | end
5 |
6 | def defaults
7 | super.merge(class: ["form-control-color"])
8 | end
9 | end
10 |
11 | Trestle::Form::Builder.register(:color_field, Trestle::Form::Fields::ColorField)
12 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/date_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::DateField < Trestle::Form::Fields::FormControl
2 | include Trestle::Form::Fields::DatePicker
3 |
4 | def field
5 | builder.raw_date_field(name, options)
6 | end
7 |
8 | def controller
9 | "datepicker"
10 | end
11 | end
12 |
13 | Trestle::Form::Builder.register(:date_field, Trestle::Form::Fields::DateField)
14 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/date_picker.rb:
--------------------------------------------------------------------------------
1 | module Trestle::Form::Fields::DatePicker
2 | def normalize_options!
3 | unless options[:prepend] == false
4 | options[:prepend] ||= options.delete(:icon) { default_icon }
5 | end
6 |
7 | super
8 | end
9 |
10 | def defaults
11 | defaults = super
12 | defaults.merge!(data: { controller: controller, allow_clear: true }) if enable_date_picker?
13 | defaults
14 | end
15 |
16 | def default_icon
17 | icon("fa fa-calendar")
18 | end
19 |
20 | def enable_date_picker?
21 | !disabled? && !readonly? && options[:picker] != false
22 | end
23 |
24 | def controller
25 | "datepicker"
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/date_select.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Form
3 | module Fields
4 | class DateSelect < Field
5 | attr_reader :html_options
6 |
7 | def initialize(builder, template, name, options={}, html_options={}, &block)
8 | super(builder, template, name, options, &block)
9 |
10 | @html_options = default_html_options.merge(html_options)
11 | end
12 |
13 | def field
14 | tag.div(class: "date-select") do
15 | builder.raw_date_select(name, options, html_options, &block)
16 | end
17 | end
18 |
19 | def default_html_options
20 | Trestle::Options.new(class: ["form-select"], disabled: readonly?, data: { controller: "select" })
21 | end
22 | end
23 | end
24 | end
25 | end
26 |
27 | Trestle::Form::Builder.register(:date_select, Trestle::Form::Fields::DateSelect)
28 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/datetime_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::DatetimeField < Trestle::Form::Fields::FormControl
2 | include Trestle::Form::Fields::DatePicker
3 |
4 | def field
5 | builder.raw_datetime_field(name, options)
6 | end
7 |
8 | def controller
9 | "datetimepicker"
10 | end
11 | end
12 |
13 | Trestle::Form::Builder.register(:datetime_field, Trestle::Form::Fields::DatetimeField)
14 | Trestle::Form::Builder.register(:datetime_local_field, Trestle::Form::Fields::DatetimeField)
15 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/datetime_select.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Form
3 | module Fields
4 | class DatetimeSelect < Field
5 | attr_reader :html_options
6 |
7 | def initialize(builder, template, name, options={}, html_options={}, &block)
8 | super(builder, template, name, options, &block)
9 |
10 | @html_options = default_html_options.merge(html_options)
11 | end
12 |
13 | def field
14 | tag.div(class: "datetime-select") do
15 | builder.raw_datetime_select(name, options, html_options, &block)
16 | end
17 | end
18 |
19 | def default_html_options
20 | Trestle::Options.new(class: ["form-select"], disabled: readonly?, data: { controller: "select" })
21 | end
22 | end
23 | end
24 | end
25 | end
26 |
27 | Trestle::Form::Builder.register(:datetime_select, Trestle::Form::Fields::DatetimeSelect)
28 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/email_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::EmailField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_email_field(name, options)
4 | end
5 | end
6 |
7 | Trestle::Form::Builder.register(:email_field, Trestle::Form::Fields::EmailField)
8 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/file_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::FileField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_file_field(name, options)
4 | end
5 | end
6 |
7 | Trestle::Form::Builder.register(:file_field, Trestle::Form::Fields::FileField)
8 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/month_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::MonthField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_month_field(name, options)
4 | end
5 | end
6 |
7 | Trestle::Form::Builder.register(:month_field, Trestle::Form::Fields::MonthField)
8 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/number_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::NumberField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_number_field(name, options)
4 | end
5 | end
6 |
7 | Trestle::Form::Builder.register(:number_field, Trestle::Form::Fields::NumberField)
8 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/password_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::PasswordField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_password_field(name, options)
4 | end
5 |
6 | def defaults
7 | super.merge(autocomplete: "new-password")
8 | end
9 | end
10 |
11 | Trestle::Form::Builder.register(:password_field, Trestle::Form::Fields::PasswordField)
12 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/radio_button_helpers.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Form
3 | module Fields
4 | module RadioButtonHelpers
5 | def inline?
6 | options[:inline]
7 | end
8 |
9 | def default_wrapper_class
10 | [
11 | "form-check",
12 | ("form-check-inline" if inline?)
13 | ].compact
14 | end
15 |
16 | def input_class
17 | ["form-check-input"]
18 | end
19 |
20 | def label_class
21 | ["form-check-label"]
22 | end
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/range_field.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Form
3 | module Fields
4 | class RangeField < Field
5 | def field
6 | builder.raw_range_field(name, options)
7 | end
8 |
9 | def defaults
10 | super.merge(class: ["form-range"])
11 | end
12 | end
13 | end
14 | end
15 | end
16 |
17 | Trestle::Form::Builder.register(:range_field, Trestle::Form::Fields::RangeField)
18 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/search_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::SearchField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_search_field(name, options)
4 | end
5 | end
6 |
7 | Trestle::Form::Builder.register(:search_field, Trestle::Form::Fields::SearchField)
8 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/tag_select.rb:
--------------------------------------------------------------------------------
1 | require_relative "select"
2 |
3 | module Trestle
4 | class Form
5 | module Fields
6 | class TagSelect < Select
7 | def initialize(builder, template, name, options={}, html_options={})
8 | super(builder, template, name, nil, options, html_options)
9 | end
10 |
11 | def default_html_options
12 | super.merge(multiple: true, class: ["tag-select"], data: { tags: true })
13 | end
14 | end
15 | end
16 | end
17 | end
18 |
19 | Trestle::Form::Builder.register(:tag_select, Trestle::Form::Fields::TagSelect)
20 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/telephone_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::TelephoneField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_telephone_field(name, options)
4 | end
5 | end
6 |
7 | Trestle::Form::Builder.register(:telephone_field, Trestle::Form::Fields::TelephoneField)
8 | Trestle::Form::Builder.register(:phone_field, Trestle::Form::Fields::TelephoneField)
9 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/text_area.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::TextArea < Trestle::Form::Fields::FormControl
2 | def defaults
3 | super.merge(rows: 5)
4 | end
5 |
6 | def field
7 | builder.raw_text_area(name, options)
8 | end
9 | end
10 |
11 | Trestle::Form::Builder.register(:text_area, Trestle::Form::Fields::TextArea)
12 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/text_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::TextField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_text_field(name, options)
4 | end
5 | end
6 |
7 | Trestle::Form::Builder.register(:text_field, Trestle::Form::Fields::TextField)
8 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/time_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::TimeField < Trestle::Form::Fields::FormControl
2 | include Trestle::Form::Fields::DatePicker
3 |
4 | def field
5 | builder.raw_time_field(name, options)
6 | end
7 |
8 | def default_icon
9 | icon("fa fa-clock-o")
10 | end
11 |
12 | def controller
13 | "timepicker"
14 | end
15 | end
16 |
17 | Trestle::Form::Builder.register(:time_field, Trestle::Form::Fields::TimeField)
18 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/time_select.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Form
3 | module Fields
4 | class TimeSelect < Field
5 | attr_reader :html_options
6 |
7 | def initialize(builder, template, name, options={}, html_options={}, &block)
8 | super(builder, template, name, options, &block)
9 |
10 | @html_options = default_html_options.merge(html_options)
11 | end
12 |
13 | def field
14 | tag.div(class: "time-select") do
15 | builder.raw_time_select(name, options, html_options, &block)
16 | end
17 | end
18 |
19 | def default_html_options
20 | Trestle::Options.new(class: ["form-select"], disabled: readonly?, data: { controller: "select" })
21 | end
22 | end
23 | end
24 | end
25 | end
26 |
27 | Trestle::Form::Builder.register(:time_select, Trestle::Form::Fields::TimeSelect)
28 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/url_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::UrlField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_url_field(name, options)
4 | end
5 | end
6 |
7 | Trestle::Form::Builder.register(:url_field, Trestle::Form::Fields::UrlField)
8 |
--------------------------------------------------------------------------------
/lib/trestle/form/fields/week_field.rb:
--------------------------------------------------------------------------------
1 | class Trestle::Form::Fields::WeekField < Trestle::Form::Fields::FormControl
2 | def field
3 | builder.raw_week_field(name, options)
4 | end
5 | end
6 |
7 | Trestle::Form::Builder.register(:week_field, Trestle::Form::Fields::WeekField)
8 |
--------------------------------------------------------------------------------
/lib/trestle/hook.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Hook
3 | require_relative "hook/helpers"
4 | require_relative "hook/set"
5 |
6 | attr_reader :name, :options, :block
7 |
8 | def initialize(name, options={}, &block)
9 | @name, @options, @block = name, options, block
10 | end
11 |
12 | def ==(other)
13 | other.is_a?(self.class) && name == other.name && options == other.options && block == other.block
14 | end
15 |
16 | def visible?(context)
17 | if options[:if]
18 | context.instance_exec(&options[:if])
19 | elsif options[:unless]
20 | !context.instance_exec(&options[:unless])
21 | else
22 | true
23 | end
24 | end
25 |
26 | def evaluate(context, *args)
27 | context.instance_exec(*args, &block)
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/lib/trestle/hook/set.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Hook
3 | class Set
4 | attr_reader :hooks
5 |
6 | def initialize
7 | @hooks = {}
8 | end
9 |
10 | def append(name, options={}, &block)
11 | hooks[name.to_s] ||= []
12 | hooks[name.to_s] << Hook.new(name.to_s, options, &block)
13 | end
14 |
15 | def any?(name)
16 | hooks.key?(name.to_s) && hooks[name.to_s].any?
17 | end
18 |
19 | def for(name)
20 | hooks.fetch(name.to_s) { [] }
21 | end
22 |
23 | def empty?
24 | hooks.empty?
25 | end
26 |
27 | def ==(other)
28 | other.is_a?(self.class) && hooks == other.hooks
29 | end
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/lib/trestle/options.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Options < Hash
3 | def self.new(hash={})
4 | self[hash]
5 | end
6 |
7 | def merge(other, &block)
8 | dup.merge!(other, &block)
9 | end
10 |
11 | def merge!(other, &block)
12 | super(other || {}) do |key, v1, v2|
13 | if v1.is_a?(Hash) && v2.is_a?(Hash)
14 | v1.merge(v2, &block)
15 | elsif v1.is_a?(Array)
16 | v1 + Array(v2)
17 | else
18 | v2
19 | end
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/trestle/scopes/definition.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Scopes
3 | class Definition
4 | attr_reader :blocks, :options
5 |
6 | def initialize
7 | @blocks = []
8 | @options = {}
9 | end
10 |
11 | def append(**defaults, &block)
12 | @blocks << Block.new(**defaults, &block)
13 | end
14 |
15 | def apply_options!(options)
16 | @options.merge!(options)
17 | end
18 |
19 | # Evaluates each of the scope blocks within the given admin context
20 | # and returns a hash of Scope objects keyed by the scope name.
21 | def evaluate(context)
22 | @blocks.map { |block| block.scopes(context) }.flatten.index_by(&:name)
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/lib/trestle/sprockets_compressor.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class SprocketsCompressor
3 | def initialize(original_compressor, excluded_files: ["trestle/admin"])
4 | @original_compressor = original_compressor
5 | @excluded_files = excluded_files
6 | end
7 |
8 | def call(input)
9 | if @excluded_files.include?(input[:name])
10 | input[:data]
11 | else
12 | @original_compressor.call(input)
13 | end
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/trestle/tab.rb:
--------------------------------------------------------------------------------
1 | require "action_view/helpers"
2 |
3 | module Trestle
4 | class Tab
5 | include ActionView::Helpers::TagHelper
6 |
7 | attr_reader :name, :options
8 |
9 | def initialize(name, **options)
10 | @name, @options = name, options
11 | end
12 |
13 | def id(tag=nil)
14 | ["tab", tag, name].compact.join("-")
15 | end
16 |
17 | def label
18 | safe_join([options[:label] || I18n.t("admin.tabs.#{name}", default: name.to_s.titleize), badge].compact, " ")
19 | end
20 |
21 | def badge
22 | tag.span(options[:badge], class: "badge") if options[:badge]
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/lib/trestle/table/builder.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | class Table
3 | class Builder < Trestle::Builder
4 | target :table
5 |
6 | def initialize(options={})
7 | @table = Table.new(options)
8 | @output_buffer = ActionView::OutputBuffer.new
9 | end
10 |
11 | def row(options={}, &block)
12 | table.row = Row.new(options, &block)
13 | end
14 |
15 | def selectable_column(options={})
16 | table.columns << SelectColumn.new(options)
17 | end
18 |
19 | def column(field, proc=nil, options={}, &block)
20 | if proc.is_a?(Hash)
21 | options = proc
22 | proc = nil
23 | end
24 |
25 | table.columns << Column.new(field, options, &(proc || block))
26 | end
27 |
28 | def actions(options={}, &block)
29 | table.columns << ActionsColumn.new(options, &block)
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/trestle/version.rb:
--------------------------------------------------------------------------------
1 | module Trestle
2 | VERSION = "0.10.1"
3 | end
4 |
--------------------------------------------------------------------------------
/sandbox/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require_relative 'config/application'
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/sandbox/app/admin/categories_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.resource(:categories) do
2 | menu do
3 | item :categories, icon: "fa fa-tags"
4 | end
5 |
6 | collection do
7 | model.alphabetical
8 | end
9 |
10 | table do
11 | selectable_column
12 | column :name, link: true, sort: { default: true }
13 | column :color do |category|
14 | status_tag category.color, :none, style: "background: #{category.color}"
15 | end
16 | actions
17 | end
18 |
19 | form modal: true do
20 | text_field :name
21 | color_field :color
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/sandbox/app/admin/components/alerts_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.admin(:alerts, scope: Components) do
2 | menu do
3 | group :components do
4 | item :alerts, icon: "fas fa-exclamation-circle", priority: 1
5 | end
6 | end
7 |
8 | helper do
9 | def alert_message(html_class)
10 | <<-HTML.html_safe
11 | This custom alert has the #{html_class}
class. This is the Link style.
12 | HTML
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/sandbox/app/admin/components/buttons_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.admin(:buttons, scope: Components) do
2 | menu do
3 | group :components do
4 | item :buttons, icon: "fas fa-caret-square-right", priority: 2
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sandbox/app/admin/components/forms_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.admin(:forms, scope: Components) do
2 | menu do
3 | group :components do
4 | item :forms, icon: "fas fa-check-square", priority: 3
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sandbox/app/admin/components/grid_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.admin(:grid, scope: Components) do
2 | menu do
3 | group :components do
4 | item :grid, icon: "fas fa-grip-horizontal", priority: 4
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sandbox/app/admin/components/icons_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.admin(:icons, scope: Components) do
2 | menu do
3 | group :components do
4 | item :icons, icon: "fas fa-icons", priority: 6
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sandbox/app/admin/components/media_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.admin(:media, scope: Components) do
2 | menu do
3 | group :components do
4 | item :media, icon: "fas fa-images", priority: 5
5 | end
6 | end
7 |
8 | # helper ImageHelper
9 | end
10 |
--------------------------------------------------------------------------------
/sandbox/app/admin/components/miscellaneous_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.admin(:miscellaneous, scope: Components) do
2 | menu do
3 | group :components do
4 | item :miscellaneous, icon: "fas fa-box-open", priority: 7
5 | end
6 | end
7 |
8 | controller do
9 | def modal
10 | render turbo_stream: turbo_stream.modal
11 | end
12 |
13 | def modal_post
14 | render turbo_stream: turbo_stream.modal
15 | end
16 | end
17 |
18 | routes do
19 | get "modal"
20 | post "modal_post"
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/sandbox/app/admin/components/theme_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.admin(:theme, scope: Components) do
2 | menu do
3 | group :components do
4 | item :theme, icon: "fas fa-palette", priority: 8
5 | end
6 | end
7 |
8 | helper do
9 | def alert_message(html_class)
10 | <<-HTML.html_safe
11 | This custom alert has the #{html_class}
class. This is the Link style.
12 | HTML
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/sandbox/app/admin/components/typography_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.admin(:typography, scope: Components) do
2 | menu do
3 | group :components do
4 | item :typography, icon: "fas fa-font", priority: 0
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sandbox/app/admin/offices_admin.rb:
--------------------------------------------------------------------------------
1 | Trestle.resource(:offices) do
2 | menu do
3 | item :offices, icon: "fas fa-building"
4 | end
5 |
6 | table do
7 | column :city, link: true
8 | column :country
9 | column :phone
10 | column :url, sort: :url do |office|
11 | link_to office.url, office.url, target: "_blank"
12 | end
13 | actions
14 | end
15 |
16 | form modal: true do
17 | row do
18 | col { text_field :city }
19 | col { text_field :country }
20 | end
21 |
22 | text_field :address_1, label: "Address"
23 | text_field :address_2, label: false
24 |
25 | divider
26 |
27 | url_field :url, prepend: icon("fas fa-link")
28 | phone_field :phone, prepend: icon("fas fa-phone-alt")
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/sandbox/app/assets/config/manifest.js:
--------------------------------------------------------------------------------
1 | //= link_tree ../images
2 | //= link_directory ../javascripts .js
3 | //= link_directory ../stylesheets .css
4 |
--------------------------------------------------------------------------------
/sandbox/app/assets/images/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrestleAdmin/trestle/020161aec0c6923f218cbf7552cc677f77204a43/sandbox/app/assets/images/.keep
--------------------------------------------------------------------------------
/sandbox/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into application.js, which will include all the files
2 | // listed below.
3 | //
4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6 | //
7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 | // compiled file. JavaScript code in this file should be added after the last require_* statement.
9 | //
10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11 | // about supported directives.
12 | //
13 | //= require_tree .
14 |
--------------------------------------------------------------------------------
/sandbox/app/assets/javascripts/trestle/custom/controllers/modal_demo/modal_controller.js:
--------------------------------------------------------------------------------
1 | var ModalDemo = ModalDemo || {}
2 | ModalDemo.ModalController = class extends Trestle.ApplicationController {
3 | static targets = ['message']
4 |
5 | submit () {
6 | const message = this.messageTarget.value
7 |
8 | if (message.length) {
9 | this.modalController.submit({ message: message })
10 | } else {
11 | alert('Message required.')
12 | }
13 | }
14 |
15 | setMessage (e) {
16 | this.messageTarget.value = e.detail.message
17 | }
18 |
19 | get modalController () {
20 | return this.application.getControllerForElementAndIdentifier(this.element, 'modal')
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/sandbox/app/assets/javascripts/trestle/custom/controllers/modal_demo/trigger_controller.js:
--------------------------------------------------------------------------------
1 | var ModalDemo = ModalDemo || {}
2 | ModalDemo.TriggerController = class extends Trestle.ApplicationController {
3 | static targets = ['status']
4 |
5 | connect () {
6 | this.setStatus('ModalDemo.Trigger controller initialized.')
7 | }
8 |
9 | setStatus (message) {
10 | this.statusTarget.innerText = message
11 | }
12 |
13 | setLoading () {
14 | this.setStatus('Loading modal...')
15 | }
16 |
17 | setLoaded () {
18 | this.setStatus('Modal successfully loaded.')
19 | }
20 |
21 | updateStatus (e) {
22 | this.setStatus(`Modal submitted with: ${e.detail.message}`)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/sandbox/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10 | * files in this directory. Styles in this file should be added after the last require_* statement.
11 | * It is generally better to create a new file per style scope.
12 | *
13 | *= require_tree .
14 | *= require_self
15 | */
16 |
--------------------------------------------------------------------------------
/sandbox/app/channels/application_cable/channel.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Channel < ActionCable::Channel::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/sandbox/app/channels/application_cable/connection.rb:
--------------------------------------------------------------------------------
1 | module ApplicationCable
2 | class Connection < ActionCable::Connection::Base
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/sandbox/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | protect_from_forgery with: :exception
3 | end
4 |
--------------------------------------------------------------------------------
/sandbox/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrestleAdmin/trestle/020161aec0c6923f218cbf7552cc677f77204a43/sandbox/app/controllers/concerns/.keep
--------------------------------------------------------------------------------
/sandbox/app/fields/custom_field.rb:
--------------------------------------------------------------------------------
1 | class CustomField < Trestle::Form::Field
2 | def initialize(builder, template, name, options={}, &block)
3 | super(builder, template, name, options, &block)
4 | end
5 |
6 | def field
7 | tag.div("Custom Field", class: "p-2 text-white bg-info font-weight-bold")
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/sandbox/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/sandbox/app/helpers/image_helper.rb:
--------------------------------------------------------------------------------
1 | module ImageHelper
2 | def random_image(width, height, seed=nil)
3 | image_tag(random_image_url(width, height, seed))
4 | end
5 |
6 | def random_image_url(width, height, seed=nil)
7 | "https://picsum.photos/seed/#{seed}/#{width}/#{height}?random"
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/sandbox/app/jobs/application_job.rb:
--------------------------------------------------------------------------------
1 | class ApplicationJob < ActiveJob::Base
2 | end
3 |
--------------------------------------------------------------------------------
/sandbox/app/mailers/application_mailer.rb:
--------------------------------------------------------------------------------
1 | class ApplicationMailer < ActionMailer::Base
2 | default from: 'from@example.com'
3 | layout 'mailer'
4 | end
5 |
--------------------------------------------------------------------------------
/sandbox/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | class ApplicationRecord < ActiveRecord::Base
2 | self.abstract_class = true
3 | end
4 |
--------------------------------------------------------------------------------
/sandbox/app/models/article.rb:
--------------------------------------------------------------------------------
1 | class Article < ApplicationRecord
2 | belongs_to :author, class_name: "User"
3 |
4 | has_and_belongs_to_many :categories
5 |
6 | scope :active, -> { where(active: true) }
7 |
8 | serialize :tags, type: Array, coder: YAML
9 |
10 | validates :title, presence: true
11 |
12 | def tags=(tags)
13 | super(tags.reject(&:blank?))
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/sandbox/app/models/category.rb:
--------------------------------------------------------------------------------
1 | class Category < ApplicationRecord
2 | validates :name, presence: true
3 |
4 | scope :alphabetical, -> { order(:name) }
5 |
6 | def to_s
7 | name
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/sandbox/app/models/color.rb:
--------------------------------------------------------------------------------
1 | ColorCategory = Struct.new(:name, :colors)
2 |
3 | Color = Struct.new(:name, :code) do
4 | def name_with_code
5 | "#{name} (#{code})"
6 | end
7 |
8 | def self.all
9 | [
10 | new("Red", "#f00"),
11 | new("Green", "#0f0"),
12 | new("Blue", "#00f")
13 | ]
14 | end
15 |
16 | def self.categorized
17 | [
18 | ColorCategory.new("Primary", [
19 | new("Red", "#f00"),
20 | new("Green", "#0f0"),
21 | new("Blue", "#00f")
22 | ]),
23 |
24 | ColorCategory.new("Secondary", [
25 | new("Yellow", "#ff0"),
26 | new("Magenta", "#f0f"),
27 | new("Cyan", "#0ff")
28 | ])
29 | ]
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/sandbox/app/models/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TrestleAdmin/trestle/020161aec0c6923f218cbf7552cc677f77204a43/sandbox/app/models/concerns/.keep
--------------------------------------------------------------------------------
/sandbox/app/models/office.rb:
--------------------------------------------------------------------------------
1 | class Office < ApplicationRecord
2 | has_many :users
3 |
4 | scope :alphabetical, ->(order=:asc) { reorder(city: order, country: order) }
5 |
6 | def display_name
7 | [city, country].join(", ")
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/sandbox/app/models/user.rb:
--------------------------------------------------------------------------------
1 | class User < ApplicationRecord
2 | belongs_to :office
3 |
4 | validates :first_name, :last_name, presence: true
5 |
6 | has_secure_password
7 |
8 | scope :alphabetical, ->(order=:asc) { reorder(last_name: order, first_name: order) }
9 |
10 | enum level: [:executive, :manager, :staff, :intern, :contractor]
11 | enum avatar_type: { "Mystery Person" => "mp", "Identicon" => "identicon", "MonsterID" => "monsterid", "Wavatar" => "wavatar", "Retro" => "retro", "RoboHash" => "robohash", "Initials" => "blank" }
12 |
13 | def full_name
14 | [first_name, last_name].join(" ")
15 | end
16 |
17 | def initials
18 | [first_name, last_name].compact.map(&:first).join.upcase
19 | end
20 |
21 | def avatar_type_value
22 | self.class.avatar_types[avatar_type]
23 | end
24 |
25 | def avatar_color
26 | "##{Digest::MD5.hexdigest(email)[0..5]}" if email
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/sandbox/app/views/admin/components/buttons/index.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for(:title, "Components: Buttons") %>
2 |
3 | <%= render layout: "layout", locals: { wrapper: false } do %>
4 | Bootstrap’s grid system uses a series of containers, rows, and columns to layout and align content. It’s built with flexbox and is fully responsive.
8 | <% end %> 9 | 10 | <% [12, 6, 4, 3, 2, 1].each do |columns| %> 11 | <%= row do %> 12 | <% columns.times do %> 13 | <%= col(lg: (12 / columns)) do %> 14 |<%= ".col-lg-#{(12 / columns)}" %>
17 | WIP
5 | <% end %> 6 | 7 |Modal POST response.
9 | <% end %> 10 | -------------------------------------------------------------------------------- /sandbox/app/views/admin/components/theme/_modal.html.erb: -------------------------------------------------------------------------------- 1 | <%= container do %> 2 |Row Style |
---|
Primary Row |
Secondary Row |
Regular Row |
This line of text contains the text-primary class.
7 |This line of text contains the text-primary-emphasis class.
8 | 9 |This line of text contains the text-secondary class.
10 |This line of text contains the text-secondary-emphasis class.
11 | 12 |This line of text is formatted as a link.
13 |This line of text is a paragraph styled as a link.
14 | <% end %> 15 | -------------------------------------------------------------------------------- /sandbox/app/views/admin/components/typography/_headings.html.erb: -------------------------------------------------------------------------------- 1 | <%= container do |c| %> 2 | <% c.sidebar class: "order-first" do %> 3 |All HTML headings, <h1>
through <h6>
, are available.
.h1
through .h6
classes are also available, for when you want to match the font styling of a heading but cannot use the associated HTML element.
Styling for common inline HTML5 elements.
5 | <% end %> 6 | 7 |You can use the mark tag to highlight text.
8 |This line of text is meant to be treated as deleted text.
This line of text is meant to be treated as no longer accurate.
This line of text is meant to be treated as an addition to the document.
11 |This line of text will render as underlined
12 |This line of text is meant to be treated as fine print.
13 |This line rendered as bold text.
14 |This line rendered as italicized text.
15 | <% end %> 16 | -------------------------------------------------------------------------------- /sandbox/app/views/admin/components/typography/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for(:title, "Components: Typography") %> 2 | 3 | <%= render layout: "layout", locals: { wrapper: false } do %> 4 |