Skip to content

Phase 5: Bootstrap 4 → Bootstrap 5 + Tabler migration - #17

Merged
gru3zi merged 11 commits into
feat/phase3-ace-removalfrom
feat/phase5-bs5-tabler
Jun 23, 2026
Merged

Phase 5: Bootstrap 4 → Bootstrap 5 + Tabler migration#17
gru3zi merged 11 commits into
feat/phase3-ace-removalfrom
feat/phase5-bs5-tabler

Conversation

@gru3zi

@gru3zi gru3zi commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Summary

Complete Bootstrap 4 → Bootstrap 5 migration replacing the Atlantis admin theme with Tabler v1.0.0-beta21 across all frontend assets.

  • 5.0 — Add @tabler/core@1.0.0-beta21 + @popperjs/core; clean WebFont families
  • 5.1 — Tabler layout shell: swap Atlantis CSS/JS for Tabler, remove bootstrap-select/ajax-bootstrap-picker/jquery-scrollbar, .wrapper.page
  • 5.2a+b+c — Atomic BS4→BS5 data-attr sweep (data-toggledata-bs-toggle etc.) across 8 HTML + 9 JS files; jQuery bridge shim for .modal()/.popover()/.tooltip() covering ~167 call sites
  • 5.3 — BS5 utility class renames: ml-*ms-*, mr-*me-*, badge-{color}text-bg-{color} (static), btn-xsbtn-sm, form-group removed, input-group-append/prepend unwrapped (30 files)
  • hotfix — Restore jQuery UI script tag (silently dropped when Atlantis removed)
  • 5.4 — Tom Select replaces bootstrap-select (shim + 3 AJAX call sites); iris_toast replaces bootstrap-notify; scrollbar CSS
  • 5.5 — DataTables 1.10.16 → 1.13.8 + BS5 CSS/JS integration shims; searchBuilder bs4→bs5
  • 5.6 — selectgroup→BS5 form-check; 30 flaticon→FA5 replacements; badge-${style} CSS compat shim; DT className cleanup
  • 5.7 — Vanilla JS sidebar toggle (78 lines) replacing Atlantis sidebar JS: mobile nav, topbar, quick-sidebar, outside-click
  • 5.8 — Modal bridge fix ({show:true} option object now calls .show()); 2 dashboard flaticon remnants
  • CR fixes — XSS fix in iris_toast (DOM APIs instead of innerHTML); Bootstrap declared dep v4→v5; context switcher TomSelect ordering fix

Test plan

  • npm run build — clean, 3.5s
  • docker restart iriswebapp_app iriswebapp_nginx — stack healthy
  • node e2e/diag-phase5-smoke.cjs — ALL PASS
  • node e2e/diag-phase5-qa.cjs — 34/34 PASS (login, sidebar toggles, modal shim, Tom Select dropdowns, DataTables, iris_toast, Milkdown notes, overview searchBuilder, alerts)
  • CodeRabbit cr review — 84 findings triaged; 3 Phase 5 issues fixed (XSS, BS version, context switcher ordering); remaining findings are pre-existing or false positives (build artifacts)

🤖 Generated with Claude Code

gru3zi and others added 11 commits June 23, 2026 06:55
- Add @tabler/core@1.0.0-beta21 and @popperjs/core@^2.11.8 to ui/package.json
- Swap vite copy target: popper.js → @popperjs/core (same dest path)
- Add vite copy targets for tabler.min.css and tabler.min.js
- Remove Flaticon and simple-line-icons from WebFont.load families in all
  4 layouts — prevents hang when font files are removed in 5.1; @font-face
  declarations in fonts.css still load via the urls injection

No visual changes. Tabler/Popper v2 assets now in dist/ ready for 5.1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CSS/JS:
- Replace bootstrap.min.css + atlantis.css → tabler.min.css in all 4 layouts
- Replace bootstrap.min.js + atlantis.min.js → tabler.min.js in all 4 layouts
- Remove atlantis-draggable-shim.js, jquery.scrollbar.min.js,
  bootstrap-select.min.css/js, ajax-bootstrap-picker.js from all layouts

Layout structure:
- class="wrapper" → class="page" in default.html/ext/centered (Tabler container)
- Gate off dark-theme.css in 3 layouts with Jinja2 comment; add in-navbar
  dismissible warning for dark mode users (data-bs-dismiss, btn-close)
- static-default.html: no wrapper div, no dark mode conditional — left intact

Icons:
- flaticon-interface-1/3/7, flaticon-shapes-1, flaticon-round → FA equivalents
  in navigation.html, navigation_ext.html, sidenav.html
- Remaining flaticons deferred to 5.6 (font still loads via fonts.css/WebFont)

Fixes:
- sidenav.html: collapse in → collapse show (BS3 remnant)
- quick-sidebar.html: btn-xs → btn-sm (×2)

Vite build clean. No Jinja2 template logic removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…patches

ATOMIC: BS5 now loaded (5.1); all plugin call sites must migrate together.

5.2a — HTML data-attribute sweep (8 include/partial files):
- data-toggle → data-bs-toggle (modal/collapse/dropdown/tab/popover/tooltip)
- data-target → data-bs-target
- data-dismiss → data-bs-dismiss (modal + alert)
- data-backdrop/trigger/content/placement/html → data-bs-* equivalents
- .close + <span>&times;</span> → <button class="btn-close"> (×5 in footer.html)
- modal-dialog class ordering: modal-lg/xl before modal-dialog → correct BS5 order
- Zero old-style data-toggle/data-dismiss remain in any HTML template

5.2b — JavaScript bridge shim + data-attr sweep:
- Add jQuery BS5 bridge shim at top of common.js: $.fn.modal/popover/tooltip
  delegate to bootstrap.Modal/Popover/Tooltip.getOrCreateInstance — covers
  ~167 call sites across 25 JS files without mechanical rewrites
- .wrapper → .page in common.js sidebar toggle handler (3 lines)
- data-toggle/data-dismiss strings in JS template literals → data-bs-* (10 files)
- Selector queries [data-toggle="popover/tooltip"] → [data-bs-toggle=...] (7 files)
- Zero old-style data-toggle remain in any JS source file

5.2c — Vendor JS patches:
- dataTables.contextualActions.min.js: data-toggle → data-bs-toggle (tooltip attr)
- bootstrap-multiselect.min.js: data-toggle="dropdown" → data-bs-toggle="dropdown"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
30 files changed (10 HTML includes/partials + 20 JS files):

Directional spacing:
- ml-N → ms-N, mr-N → me-N (margin-start/end)
- pl-N → ps-N, pr-N → pe-N (padding-start/end)
- float-left/right → float-start/end, pull-left/right → float-start/end

Typography:
- text-left → text-start, text-right → text-end (~217 occurrences)
- font-weight-bold/light/normal → fw-bold/light/normal

Badges (static only — dynamic badge-${style} deferred, needs CSS compat shim):
- badge-{color} → text-bg-{color} across alerts.js, timeline, dashboard, etc.

Forms:
- custom-select → form-select
- form-group class removed from wrapper divs (divs kept)
- input-group-append/prepend wrappers unwrapped in navigation.html + alerts.js

Buttons:
- btn-xs → btn-sm in case.timeline.js (×10 template literals)

Atlantis negative margins:
- mt--N → mt-nN in sidenav.html (×1) and alerts.js (×4)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jQuery UI (jquery-ui-1.12.1.custom) was bundled inside atlantis.min.js.
When 5.1 removed Atlantis, draggable/resizable broke silently. The file
was already vendored; just missing the <script> tag.

Added after jquery.min.js in all 4 layouts — must load before Tabler/common.js.

Caught by new diag-phase5-smoke.cjs smoke test (login, Tabler layout check,
modal shim verification, JS error monitoring, manage page load).
Playwright config: baseURL now reads process.env.BASE_URL for local testing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.4a — Tom Select replaces bootstrap-select + ajax-bootstrap-picker:
- Add tom-select@2.3.1 to package.json; copy CSS+JS via vite
- Add tom-select.bootstrap5.min.css + tom-select.min.js to all 4 layouts
- $.fn.selectpicker shim in common.js (window._irisSelects map) covers all
  26 non-AJAX call sites without mechanical rewrites
- Replace 3 ajaxSelectPicker AJAX call sites with TomSelect load callbacks:
  common.js #user_context, alerts.js #mergeAlertCaseSelect (×2)
- savedFilters: shown.bs.select → dropdown_open, hide.bs.select → dropdown_close
- Remove dead bootstrap-select.min.css from header_case.html

5.4b — iris_toast replaces bootstrap-notify:
- New ui/src/lib/iris-toast.js (BS5 Toast, position fixed top-right, 3s autohide)
- 3 call paths updated: scripts.html wrappers, common.js runtime definitions,
  case.pipelines.js raw $.notify → iris_toast()
- bootstrap-notify script removed from all 4 layouts
- flaticon-error icon → fas fa-exclamation-circle in iris-toast

5.4c — jquery-scrollbar CSS replacement:
- overflow-y: auto CSS added to layouts (scrollbar.min.js removed in 5.1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 10 datatables.net npm packages (core, bs5, buttons, responsive,
  select, searchbuilder — each with -bs5 variant)
- Copy BS5 CSS/JS shims to assets/js/plugin/datatables-bs5/ and css/
- Load dataTables.bootstrap5.min.js in all 4 layouts after the existing
  datatables.min.js bundle (overrides BS4 renderer)
- header_case.html: swap BS4 DT CSS for BS5 equivalents
- footer_case.html: add buttons/select/responsive BS5 shims (dataTables.bootstrap5
  already loaded by layout, deduped)
- overview.html: dataTables.searchBuilder.bs4.js → searchBuilder.bootstrap5.min.js
- 5 blueprint templates (activities, dashboard, dim_tasks, manage_cases, search):
  swap BS4 DT CSS for BS5 equivalents + add BS5 shim loads

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New ui/src/lib/sidebar-toggle.js (78 lines, no jQuery):
  - .sidenav-toggler click → toggles nav_open on .page (mobile sidebar)
  - Outside-click on .page.nav_open → closes sidebar (with contains() guard)
  - .topbar-toggler click → toggles topbar_open on .page
  - .quick-sidebar-toggler → toggles quick_sidebar_open on html element
  - .close-quick-sidebar → removes quick_sidebar_open
  - Preserves existing common.js .toggle-sidebar (desktop minimize) untouched
- Added copy target in vite.config.js → assets/js/iris/sidebar-toggle.js
- Script loaded in all 4 layouts after tabler.min.js, before common.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.6A — selectgroup → BS5 form-check:
- alerts.js: 4-checkbox selectgroup-pills block → d-flex flex-wrap gap-2
  with form-check form-check-inline; all onclick/name/value preserved

5.6B — flaticon → FA5 (30 replacements, 6 files):
- navigation.html + navigation_ext.html: 3 each (refresh, database, plus)
- sidenav.html: 12 (home, network-wired, bell, search, list, user, cog, etc.)
- quick-sidebar.html: 10 (times, camera, inbox, laptop, file-alt, stopwatch...)
- datastore-sidebar.html: 1 (times)
- case.timeline.js: 1 (stopwatch), dashboard.js: 2 (bell, check-circle)
- Ambiguous icons marked with <!-- TODO: icon review --> comment

5.6C — badge-${style} CSS compat shim added to all 4 layouts:
- 8 rules (primary/secondary/success/danger/warning/info/light/dark)
- Covers DB-driven dynamic badge class names in common.js

5.6D — DataTables className cleanup (16 occurrences, 5 JS files):
- btn-border btn-round removed from activities.js, dashboard.js,
  dim_tasks.js, overview.js, search.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…icons

- BS5 jQuery bridge: add object-action branch — when action is {show:true},
  call instance.show() after getOrCreateInstance(); fixes silent fail across
  all 52 modal call sites that pass {show:true} as options object
- dashboard/index.html: flaticon-file-1 → fas fa-file-alt (cases stat card)
- dashboard/index.html: flaticon-suitcase → fas fa-briefcase (user cases card)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cher

SEC: iris-toast.js — replace innerHTML concatenation with DOM APIs
- message is now set via createTextNode() (XSS-safe, no markup injection)
- iconHtml uses insertAdjacentHTML (controlled FA icon strings only)
- close button built via createElement (no user data in attributes)

FIX: package.json — bootstrap ^4.0.0 → ^5.3.0
- Aligns declared dependency with actual BS5 usage (Tabler bundles BS5;
  the bootstrap package was orphaned after 5.1 removed bootstrap.min.js
  from layouts, but the declaration was incorrect)

FIX: common.js load_context_switcher() ordering
- context_data_parser(data, false) called BEFORE TomSelect init so DOM
  <option> elements exist when TomSelect scans the <select>
- TomSelect instance created, stored in window._irisSelects['user_context']
- sync() + setValue() + modal show called AFTER instance is ready
- Fixes: context switcher showed an empty dropdown on first open

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gru3zi
gru3zi merged commit 7cfff3d into feat/phase3-ace-removal Jun 23, 2026
1 check passed
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.

1 participant