refactor(stimulus): eager load stimulus controllers
This commit is contained in:
parent
ea18c2b9ba
commit
eba1973d5f
11 changed files with 69 additions and 68 deletions
|
@ -1,6 +0,0 @@
|
||||||
import 'trix';
|
|
||||||
import '@rails/actiontext';
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
return null;
|
|
||||||
}
|
|
|
@ -1,12 +1,25 @@
|
||||||
import Chartkick from 'chartkick';
|
import { Controller } from '@hotwired/stimulus';
|
||||||
import Highcharts from 'highcharts';
|
|
||||||
import { toggle, delegate } from '@utils';
|
import { toggle, delegate } from '@utils';
|
||||||
|
|
||||||
export default function () {
|
export class ChartkickController extends Controller {
|
||||||
return null;
|
async connect() {
|
||||||
|
const Highcharts = await import('highcharts');
|
||||||
|
const Chartkick = await import('chartkick');
|
||||||
|
|
||||||
|
Chartkick.use(Highcharts);
|
||||||
|
const reflow = (nextChartId?: string) =>
|
||||||
|
nextChartId && Chartkick.charts[nextChartId]?.getChartObject()?.reflow();
|
||||||
|
|
||||||
|
delegate('click', '[data-toggle-chart]', (event) =>
|
||||||
|
toggleChart(event as MouseEvent, reflow)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleChart(event: MouseEvent) {
|
function toggleChart(
|
||||||
|
event: MouseEvent,
|
||||||
|
reflow: (nextChartId?: string) => void
|
||||||
|
) {
|
||||||
const nextSelectorItem = event.target as HTMLButtonElement,
|
const nextSelectorItem = event.target as HTMLButtonElement,
|
||||||
chartClass = nextSelectorItem.dataset.toggleChart,
|
chartClass = nextSelectorItem.dataset.toggleChart,
|
||||||
nextChart = chartClass
|
nextChart = chartClass
|
||||||
|
@ -30,9 +43,5 @@ function toggleChart(event: MouseEvent) {
|
||||||
nextChart && toggle(nextChart);
|
nextChart && toggle(nextChart);
|
||||||
|
|
||||||
// Reflow needed, see https://github.com/highcharts/highcharts/issues/1979
|
// Reflow needed, see https://github.com/highcharts/highcharts/issues/1979
|
||||||
nextChartId && Chartkick.charts[nextChartId]?.getChartObject()?.reflow();
|
reflow(nextChartId);
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate('click', '[data-toggle-chart]', toggleChart);
|
|
||||||
|
|
||||||
Chartkick.use(Highcharts);
|
|
|
@ -1,32 +0,0 @@
|
||||||
import { Application } from '@hotwired/stimulus';
|
|
||||||
|
|
||||||
import { AutofocusController } from './autofocus_controller';
|
|
||||||
import { AutosaveController } from './autosave_controller';
|
|
||||||
import { AutosaveStatusController } from './autosave_status_controller';
|
|
||||||
import { GeoAreaController } from './geo_area_controller';
|
|
||||||
import { MenuButtonController } from './menu_button_controller';
|
|
||||||
import { PersistedFormController } from './persisted_form_controller';
|
|
||||||
import { ReactController } from './react_controller';
|
|
||||||
import { ScrollToController } from './scroll_to_controller';
|
|
||||||
import { SortableController } from './sortable_controller';
|
|
||||||
import { TurboEventController } from './turbo_event_controller';
|
|
||||||
import { TurboInputController } from './turbo_input_controller';
|
|
||||||
import { TurboPollController } from './turbo_poll_controller';
|
|
||||||
import { TypeDeChampEditorController } from './type_de_champ_editor_controller';
|
|
||||||
import { IBANInputController } from './iban_input_controller';
|
|
||||||
|
|
||||||
const Stimulus = Application.start();
|
|
||||||
Stimulus.register('autofocus', AutofocusController);
|
|
||||||
Stimulus.register('autosave-status', AutosaveStatusController);
|
|
||||||
Stimulus.register('autosave', AutosaveController);
|
|
||||||
Stimulus.register('geo-area', GeoAreaController);
|
|
||||||
Stimulus.register('menu-button', MenuButtonController);
|
|
||||||
Stimulus.register('persisted-form', PersistedFormController);
|
|
||||||
Stimulus.register('react', ReactController);
|
|
||||||
Stimulus.register('scroll-to', ScrollToController);
|
|
||||||
Stimulus.register('sortable', SortableController);
|
|
||||||
Stimulus.register('turbo-event', TurboEventController);
|
|
||||||
Stimulus.register('turbo-input', TurboInputController);
|
|
||||||
Stimulus.register('turbo-poll', TurboPollController);
|
|
||||||
Stimulus.register('type-de-champ-editor', TypeDeChampEditorController);
|
|
||||||
Stimulus.register('iban-input', IBANInputController);
|
|
|
@ -18,7 +18,7 @@ export function registerComponents(components: Record<string, Loader>): void {
|
||||||
// Example:
|
// Example:
|
||||||
// <div data-controller="react" data-react-component-value="ComboMultiple" data-react-props-value="{}"></div>
|
// <div data-controller="react" data-react-component-value="ComboMultiple" data-react-props-value="{}"></div>
|
||||||
//
|
//
|
||||||
export class ReactController extends Controller {
|
export default class ReactController extends Controller {
|
||||||
static values = {
|
static values = {
|
||||||
component: String,
|
component: String,
|
||||||
props: Object
|
props: Object
|
||||||
|
|
8
app/javascript/controllers/trix_controller.ts
Normal file
8
app/javascript/controllers/trix_controller.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
|
||||||
|
export class TrixController extends Controller {
|
||||||
|
connect() {
|
||||||
|
import('trix');
|
||||||
|
import('@rails/actiontext');
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import '../shared/polyfills';
|
||||||
import Rails from '@rails/ujs';
|
import Rails from '@rails/ujs';
|
||||||
import * as ActiveStorage from '@rails/activestorage';
|
import * as ActiveStorage from '@rails/activestorage';
|
||||||
import * as Turbo from '@hotwired/turbo';
|
import * as Turbo from '@hotwired/turbo';
|
||||||
|
import { Application } from '@hotwired/stimulus';
|
||||||
|
|
||||||
import '../shared/activestorage/ujs';
|
import '../shared/activestorage/ujs';
|
||||||
import '../shared/remote-poller';
|
import '../shared/remote-poller';
|
||||||
|
@ -10,7 +11,7 @@ import '../shared/toggle-target';
|
||||||
import '../shared/ujs-error-handling';
|
import '../shared/ujs-error-handling';
|
||||||
|
|
||||||
import { registerComponents } from '../controllers/react_controller';
|
import { registerComponents } from '../controllers/react_controller';
|
||||||
import '../controllers';
|
import { registerControllers } from '../shared/stimulus-loader';
|
||||||
|
|
||||||
import '../new_design/form-validation';
|
import '../new_design/form-validation';
|
||||||
import '../new_design/procedure-context';
|
import '../new_design/procedure-context';
|
||||||
|
@ -41,7 +42,6 @@ import {
|
||||||
} from '../new_design/fc-fusion';
|
} from '../new_design/fc-fusion';
|
||||||
|
|
||||||
registerComponents({
|
registerComponents({
|
||||||
Chartkick: () => import('../components/Chartkick'),
|
|
||||||
ComboAdresseSearch: () => import('../components/ComboAdresseSearch'),
|
ComboAdresseSearch: () => import('../components/ComboAdresseSearch'),
|
||||||
ComboAnnuaireEducationSearch: () =>
|
ComboAnnuaireEducationSearch: () =>
|
||||||
import('../components/ComboAnnuaireEducationSearch'),
|
import('../components/ComboAnnuaireEducationSearch'),
|
||||||
|
@ -54,10 +54,12 @@ registerComponents({
|
||||||
ComboPaysSearch: () => import('../components/ComboPaysSearch'),
|
ComboPaysSearch: () => import('../components/ComboPaysSearch'),
|
||||||
ComboRegionsSearch: () => import('../components/ComboRegionsSearch'),
|
ComboRegionsSearch: () => import('../components/ComboRegionsSearch'),
|
||||||
MapEditor: () => import('../components/MapEditor'),
|
MapEditor: () => import('../components/MapEditor'),
|
||||||
MapReader: () => import('../components/MapReader'),
|
MapReader: () => import('../components/MapReader')
|
||||||
Trix: () => import('../components/Trix')
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const application = Application.start();
|
||||||
|
registerControllers(application);
|
||||||
|
|
||||||
// This is the global application namespace where we expose helpers used from rails views
|
// This is the global application namespace where we expose helpers used from rails views
|
||||||
const DS = {
|
const DS = {
|
||||||
fire: (eventName, data) => Rails.fire(document, eventName, data),
|
fire: (eventName, data) => Rails.fire(document, eventName, data),
|
||||||
|
|
30
app/javascript/shared/stimulus-loader.ts
Normal file
30
app/javascript/shared/stimulus-loader.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { Application } from '@hotwired/stimulus';
|
||||||
|
import invariant from 'tiny-invariant';
|
||||||
|
|
||||||
|
const controllers = import.meta.globEager('../controllers/*.{ts,tsx}');
|
||||||
|
|
||||||
|
export function registerControllers(application: Application) {
|
||||||
|
for (const [path, mod] of Object.entries(controllers)) {
|
||||||
|
const [filename] = path.split('/').reverse();
|
||||||
|
const name = filename
|
||||||
|
.replace(/_/g, '-')
|
||||||
|
.replace(/-controller\.(ts|tsx)$/, '');
|
||||||
|
if (name != 'application') {
|
||||||
|
if (mod.default) {
|
||||||
|
console.debug(`Registered default export for "${name}" controller`);
|
||||||
|
application.register(name, mod.default);
|
||||||
|
} else {
|
||||||
|
const exports = Object.entries(mod);
|
||||||
|
invariant(
|
||||||
|
exports.length == 1,
|
||||||
|
`Expected a single export but ${exports.length} exports were found for "${name}" controller`
|
||||||
|
);
|
||||||
|
const [exportName, exportMod] = exports[0];
|
||||||
|
console.debug(
|
||||||
|
`Registered named export "${exportName}" for "${name}" controller`
|
||||||
|
);
|
||||||
|
application.register(name, exportMod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
app/javascript/types.d.ts
vendored
2
app/javascript/types.d.ts
vendored
|
@ -22,3 +22,5 @@ declare module '@tmcw/togeojson/dist/togeojson.es.js' {
|
||||||
|
|
||||||
declare module 'react-coordinate-input';
|
declare module 'react-coordinate-input';
|
||||||
declare module 'chartkick';
|
declare module 'chartkick';
|
||||||
|
declare module 'trix';
|
||||||
|
declare module '@rails/actiontext';
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
-# Load Trix lazily, by using our React lazy-loader.
|
|
||||||
-# (Trix itself doesn't use React though)
|
|
||||||
= react_component('Trix')
|
|
||||||
|
|
||||||
= f.label :subject do
|
= f.label :subject do
|
||||||
Objet de l'email
|
Objet de l'email
|
||||||
%span.mandatory *
|
%span.mandatory *
|
||||||
|
@ -12,7 +8,7 @@
|
||||||
%span.mandatory *
|
%span.mandatory *
|
||||||
= f.rich_text_area :rich_body, required: true, class: "mb-4"
|
= f.rich_text_area :rich_body, required: true, class: "mb-4"
|
||||||
|
|
||||||
#tags-table
|
#tags-table{ 'data-controller': 'trix' }
|
||||||
%h2.add-tag-title
|
%h2.add-tag-title
|
||||||
Insérer une balise
|
Insérer une balise
|
||||||
%p.notice
|
%p.notice
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
.statistiques
|
.statistiques{ 'data-controller': 'chartkick' }
|
||||||
-# Load Chartkick lazily, by using our React lazy-loader.
|
|
||||||
-# (Chartkick itself doesn't use React though)
|
|
||||||
= react_component('Chartkick')
|
|
||||||
|
|
||||||
%h1.new-h1= title
|
%h1.new-h1= title
|
||||||
.stat-cards
|
.stat-cards
|
||||||
- if @usual_traitement_time.present?
|
- if @usual_traitement_time.present?
|
||||||
|
|
|
@ -2,11 +2,7 @@
|
||||||
- content_for :footer do
|
- content_for :footer do
|
||||||
= render partial: "root/footer"
|
= render partial: "root/footer"
|
||||||
|
|
||||||
.statistiques
|
.statistiques{ 'data-controller': 'chartkick' }
|
||||||
-# Load Chartkick lazily, by using our React lazy-loader.
|
|
||||||
-# (Chartkick itself doesn't use React though)
|
|
||||||
= react_component('Chartkick')
|
|
||||||
|
|
||||||
%h1.new-h1 Statistiques
|
%h1.new-h1 Statistiques
|
||||||
|
|
||||||
.stat-cards
|
.stat-cards
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue