Skip to content

Conversation

mshibuya
Copy link
Member

@mshibuya mshibuya commented Jan 4, 2022

image

Closes #3083

Reason for upgrading Bootstrap to 5

Reason for replacing Bootstrap Datetimepicker with Flatpickr

  • Bootstrap Datetimepicker depends on Bootstrap 3. Since we're upgrading Bootstrap, it also needs to be updated.
  • Bootstrap Datetimepicker also depends on momentjs, which is a project stated as in maintenance mode.

Considered options

  1. Keep using Bootstrap Datetimepicker
    • Applying a minor patch may enable us to keep using this.
    • But this version is no longer maintained, with the project name changed to Tempus Dominus below.
  2. Migrate to Tempus Dominus v5
    • This is a stable version, but it doesn't come with Bootstrap 5 integration (only 3 and 4).
    • Also this depends on jQuery, which contradicts with our general direction of removing it.
  3. Migrate to Tempus Dominus v6
    • Having no jQuery dependency is good, but it's still in alpha.
  4. Migrate to Flatpickr with Day.js
    • Flatpickr having no jQuery dependency is good.
    • Also Day.js can provide functionality equivalent to momentjs, and it can easily be integrated with Flatpickr.
    • But I found working with Day.js can take a bit effort, especially with i18n things.
  5. Migrate to Flatpickr without a date library
    • This is the option I decided to use, it is simple enough while covering majority of usecases.
    • But this will require users to rewrite their momentjs_format to Flatpickr's one if they use it.
  6. Migrate to other datepicker libraries
    • I took a glance at many other libraries, but many of them
      • have jQuery dependency, or dependency for other big libraries we don't want.
      • have appearances which I don't like so much (just my personal preference...!).
      • are not so actively maintained.
    • If you're aware of other potential candidates please let me know!

Also removed old theming functionality, since existing ones are not compatible with Bootstrap 5
@coveralls
Copy link

coveralls commented Jan 5, 2022

Pull Request Test Coverage Report for Build 1701174677

  • 24 of 26 (92.31%) changed or added relevant lines in 7 files are covered.
  • 9 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.3%) to 95.664%

Changes Missing Coverage Covered Lines Changed/Added Lines %
lib/rails_admin/config/fields/types/datetime.rb 3 4 75.0%
lib/rails_admin/support/datetime.rb 5 6 83.33%
Files with Coverage Reduction New Missed Lines %
app/controllers/rails_admin/application_controller.rb 9 80.0%
Totals Coverage Status
Change from base Build 1671034350: -0.3%
Covered Lines: 3640
Relevant Lines: 3805

💛 - Coveralls

Copy link
Contributor

@codealchemy codealchemy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this ready for review (and if so, would you have any additional notes / guidance for reviewers)?

Bootstrap 5 is a welcome (and significant!) change - and I started looking at the most obvious differences from the current UI - but there's quite a bit here and I'm not sure how much style / UX changes are intended, so stopped short of going further.

<%= t('admin.loading') %>
</div>
<nav class="navbar navbar-default navbar-fixed-top">
<nav class="navbar navbar-expand-xl fixed-top navbar-dark bg-primary border-bottom">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep the same breakpoint as before, as well as the same color / styling

Suggested change
<nav class="navbar navbar-expand-xl fixed-top navbar-dark bg-primary border-bottom">
<nav class="navbar navbar-expand-md fixed-top navbar-light bg-light border-bottom">

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right about navbar-expand-md, but navbar-dark bg-primary are intentional. That was to make theming functionality(explained later) to stand out when using other themes, instead of just showing grayish navbar.

@RocKhalil
Copy link
Contributor

A BIG YES FOR THIS!
I was going to work on it this coming weekend, and just saw this PR which made me happy!

@mshibuya I can review / help if you want, let me know if you need anything for this

@mshibuya
Copy link
Member Author

mshibuya commented Jan 6, 2022

@codealchemy Sorry for not giving enough context, I was lazy 🙇
I will start leaving some comments for notable changes, but it may take some time.

@RocKhalil Your review is of course welcome! Please feel free to leave questions or comments 🙏

].compact.join.html_safe
if (edit_action = RailsAdmin::Config::Actions.find(:edit, controller: controller, abstract_model: abstract_model, object: _current_user)).try(:authorized?)
link_to content, rails_admin.url_for(action: edit_action.action_name, model_name: abstract_model.to_param, id: _current_user.id, controller: 'rails_admin/main')
link_to content, rails_admin.url_for(action: edit_action.action_name, model_name: abstract_model.to_param, id: _current_user.id, controller: 'rails_admin/main'), class: 'nav-link'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of these kind of changes are to keep up with the change in Bootstrap 5, like navbar needing nav-item and nav-link class for elements inside it.
https://getbootstrap.com/docs/5.1/components/navbar/

content_tag :li, class: 'dropdown', style: 'float:right' do
content_tag(:a, class: 'dropdown-toggle', data: {toggle: 'dropdown'}, href: '#') { t('admin.misc.bulk_menu_title').html_safe + ' ' + '<b class="caret"></b>'.html_safe } +
content_tag :li, class: 'nav-item dropdown dropdown-menu-end' do
content_tag(:a, class: 'nav-link dropdown-toggle', data: {'bs-toggle': 'dropdown'}, href: '#') { t('admin.misc.bulk_menu_title').html_safe + ' ' + '<b class="caret"></b>'.html_safe } +
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also data-toggle or data-target need to be change to data-bs-toggle or data-bs-target.

return if nested_field_association?(field, nested_in)

@template.content_tag(:div, class: "form-group control-group #{field.type_css_class} #{field.css_class} #{'error' if field.errors.present?}", id: "#{dom_id(field)}_field") do
@template.content_tag(:div, class: "control-group row mb-3 #{field.type_css_class} #{field.css_class} #{'error' if field.errors.present?}", id: "#{dom_id(field)}_field") do
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

form-group is no longer there, so replaced with row.

<li class="disabled">
<a href="#">
<li class="page-item disabled">
<a href="#" class="page-link">
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pagination structure was also updated in Bootstrap 5.
https://getbootstrap.com/docs/5.1/components/pagination/

@@ -1,9 +1,5 @@
<ul class="nav nav-pills nav-stacked">
<ul class="col-sm-3 col-md-2 btn-toggle-nav list-unstyled bg-light">
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I struggled a lot with this change because position: fixed is used here, but finally got equivalent appearance.

<div class="btn-group" data-toggle="buttons">
<% {'1': true, '0': false, '': nil}.each do |text, value| %>
<label class="<%= [field.css_classes[value], ("active" if field.form_value == value)].compact.join(' ') %> btn btn-default">
<%= form.radio_button field.method_name, text, field.html_attributes.reverse_merge({ checked: field.form_value == value, required: field.required}) %>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting an input element inside the label seemed not to work in Bootstrap 5, hence this structural change.

<div class="col-sm-2">
<%= form.send field.view_helper, field.method_name, field.html_attributes.reverse_merge({class: 'form-control', value: field.form_value}) %>
</div>
</div>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for limiting width of the input element.

<div class="controls col-sm-10" data-nestedmany="true">
<div class="btn-group">
<a class="<%= (field.active? ? 'active' : '') %> btn btn-info toggler" data-target="<%= form.jquery_namespace(field) %> > .tab-content, <%= form.jquery_namespace(field) %> > .controls > .nav" data-toggle="button">
<a class="<%= (field.active? ? 'active' : 'active') %> btn btn-info toggler" data-bs-target="<%= form.jquery_namespace(field) %> .collapse" data-bs-toggle="collapse" role="button">
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This active is my mistake - I forgot to remove it after testing behavior when active.

</button>
<% end %>
<button class="btn btn-default" data-disable-with="<%= t("admin.form.cancel") %>" formnovalidate="<%= true %>" name="_continue" type="submit">
<button class="btn btn-light" data-disable-with="<%= t("admin.form.cancel") %>" formnovalidate="<%= true %>" name="_continue" type="submit">
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btn-default is no more.

@@ -1,3 +1,3 @@
<%= rails_admin_form_for @object, url: edit_path(@abstract_model, @object.id), as: @abstract_model.param_key, html: { method: "put", multipart: true, class: "form-horizontal denser", data: { title: @page_name } } do |form| %>
<%= rails_admin_form_for @object, url: edit_path(@abstract_model, @object.id), as: @abstract_model.param_key, html: { method: "put", multipart: true, class: "main", data: { title: @page_name } } do |form| %>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

form-horizontal is no more, and added main class to be used for applying our custom styles.

<% sort_direction = (sort_reverse == 'true' ? "headerSortUp" : "headerSortDown" if selected) %>
<% end %>
<th class="<%= [property.sortable && "header pjax", property.sortable && sort_direction, property.sticky? && 'sticky', property.css_class, property.type_css_class].compact.join(' ') %>" data-href="<%= property.sortable && sort_location %>" rel="tooltip" title="<%= property.hint %>">
<th class="<%= [property.sortable && "header pjax", property.sortable && sort_direction, property.sticky? && 'sticky', property.css_class, property.type_css_class].select(&:present?).join(' ') %>" data-href="<%= property.sortable && sort_location %>" rel="tooltip" title="<%= property.hint %>">
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use of compact resulted in false showing up as CSS class, so this change.

'%z' => 'ZZ', # Time zone as hour and minute offset from UTC (e.g. +0900)
'%:z' => 'Z', # Time zone as hour and minute offset from UTC with a colon (e.g. +09:00),
# Ruby format options as a key and flatpickr format options as a value
FLATPICKR_TRANSLATIONS = {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All format options are translated into Flatpickr's ones.
https://flatpickr.js.org/formatting/

.addClass(index == 0 ? "default" : "between")
.css("display", visible ? "inline-block" : "none")
.html(
$('<input type="hidden" />')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flatpickr's altInput functionality enabled us to remove this hidden input.

is_expected.to have_content 'New Field test'
attach_file 'Carrierwave asset', file_path('test.jpg')
find('#modal .save-action').click
find('#modal .save-action').click # do it again, as a workaround for intermittent failure
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😓

document.dispatchEvent(event);

form.bind("ajax:complete", function (event) {
console.log(event);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to remove debug stuff 💦

widget.dialog = $(
'<div id="modal" class="modal fade">\
<div class="modal-dialog">\
<div class="modal-dialog modal-lg">\
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the modal wider

.tab-pane {
@include clearfix;
border-left: 5px solid #049cdb;
border-left: 5px solid map-get($theme-colors, primary);
Copy link
Member Author

@mshibuya mshibuya Jan 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoided putting color values directly, for the sake of theming functionality.

@@ -1 +1,3 @@
/* RailsAdmin SASS variables */

$font-size-base: 0.85rem !default;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bootstrap5's default font size is slightly larger than Bootstrap3, so changing it smaller

position: absolute;
cursor: default;
z-index: 1051 !important;
z-index: 1056 !important;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Autocomplete popup need to come in front of modals.

@mshibuya
Copy link
Member Author

mshibuya commented Jan 7, 2022

So about theming. Since we already have webpacker-support in place we can easily integrate with Bootstrap themes like Bootswatch.

$ yarn add bootswatch

app/javascript/stylesheets/rails_admin.scss

+ @import "~bootswatch/dist/journal/variables";
  @import "~rails_admin/src/rails_admin/styles/base.scss";
+ @import "~bootswatch/dist/journal/bootswatch";

and you will get

localhost_3000_ (1)

Don't you think it's cool?

- Fix inconsistent breakpoint
- Remove debug stuffs
overflow-x: auto;
.table {
margin-bottom: 0;
/* To silence Popper's warning: 'CSS "margin" styles cannot be used...' */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To fix the icon rendering against the span text in the nav
Screen Shot 2022-01-07 at 13 14 18

Suggested change
/* To silence Popper's warning: 'CSS "margin" styles cannot be used...' */
a > i {
padding: 0 0.3rem;
}
/* To silence Popper's warning: 'CSS "margin" styles cannot be used...' */

though it may be worth considering having a high-level rule for i in general (to fix the same issue elsewhere in the UI, such as removing a filter option)
Screen Shot 2022-01-07 at 13 14 22

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a whitespace between icon and text might be the better way, since we're doing so a lot elsewhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good (assuming that wouldn't cause issues with RTL-rendered content - which doesn't seem to be the case but mentioning it as a concern to be sure)

<% visible_fields = @model_config.export.with(view: self, object: @abstract_model.model.new, controller: self.controller).visible_fields %>
<%= form_tag export_path(params.merge(all: true)), method: 'post', class: 'form-horizontal' do %>
<%= form_tag export_path(params.merge(all: true)), method: 'post', class: "main" do %>
<input name="send_data" type="hidden" value="true">/</input>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Not related to the bootstrap changes but noticed in review) this is rendering the / to the page, seems to have come from aa6ef95

- Prevent `true` showing up as a css class
- form-control-sm must come with form-control: https://getbootstrap.com/docs/5.1/forms/form-control/#sizing
- btn-small didn't have any effect
- Fix action menu having too narrow gap between icon and text
@mshibuya mshibuya changed the title Upgrade Bootstrap to 5.1.3 Upgrade Bootstrap to 5.1.3 with migrating datetimepicker to Flatpickr Jan 15, 2022
@mshibuya
Copy link
Member Author

Let me merge this for now, feel free to leave comments here and I'll address them!

@mshibuya mshibuya merged commit 6878670 into master Jan 16, 2022
@mshibuya mshibuya deleted the bootstrap5 branch January 16, 2022 08:22
q3aiml added a commit to q3aiml/rails_admin that referenced this pull request Mar 10, 2022
During the bootstrap 5 update in 6878670 (railsadminteam#3455) this class was changed from
`content` to `container`. The `container` class, unlike `content`, has a max
width of 1320px. Restore prior behavior of using the full width by using
`container-fluid` to avoid wasted whitespace.
q3aiml added a commit to q3aiml/rails_admin that referenced this pull request Mar 10, 2022
During the bootstrap 5 update in 6878670 (railsadminteam#3455) this class was changed from
`content` to `container`. The `container` class, unlike `content`, has a max
width of 1320px. Restore prior behavior of using the full width by using
`container-fluid` to avoid wasted whitespace.
q3aiml added a commit to q3aiml/rails_admin that referenced this pull request Mar 10, 2022
During the bootstrap 5 update in 6878670 (railsadminteam#3455) this class was changed from
`content` to `container`. The `container` class, unlike `content`, has a max
width of 1320px. Restore prior behavior of using the full width by using
`container-fluid` to avoid wasted whitespace.
q3aiml added a commit to q3aiml/rails_admin that referenced this pull request Mar 10, 2022
During the bootstrap 5 update in 6878670 (railsadminteam#3455) this class was changed from
`content` to `container`. The `container` class, unlike `content`, has a max
width of 1320px. Restore prior behavior of using the full width by using
`container-fluid` to avoid wasted whitespace.
q3aiml added a commit to q3aiml/rails_admin that referenced this pull request Mar 10, 2022
During the bootstrap 5 update in 6878670 (railsadminteam#3455) this class was changed from
`content` to `container`. The `container` class, unlike `content`, has a max
width of 1320px. Restore prior behavior of using the full width by using
`container-fluid` to avoid wasted whitespace.
q3aiml added a commit to q3aiml/rails_admin that referenced this pull request Mar 10, 2022
During the bootstrap 5 update in 6878670 (railsadminteam#3455) this class was changed from
`content` to `container`. The `container` class, unlike `content`, has a max
width of 1320px. Restore prior behavior of using the full width by using
`container-fluid` to avoid wasted whitespace.
mshibuya pushed a commit that referenced this pull request Mar 11, 2022
During the bootstrap 5 update in 6878670 (#3455) this class was changed from
`content` to `container`. The `container` class, unlike `content`, has a max
width of 1320px. Restore prior behavior of using the full width by using
`container-fluid` to avoid wasted whitespace.
mshibuya pushed a commit that referenced this pull request Mar 13, 2022
During the bootstrap 5 update in 6878670 (#3455) this class was changed from
`content` to `container`. The `container` class, unlike `content`, has a max
width of 1320px. Restore prior behavior of using the full width by using
`container-fluid` to avoid wasted whitespace.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

migrate to bootstrap 5
4 participants