= render "shared/modal",
id: "create_route_modal",
class: "modal-xl",
data: { \
bs_focus: false, bs_backdrop: "static", bs_keyboard: "false",
controller: "route-new", route_new_presets_value: {},
}
.modal-header.border-primary.bg-primary.bg-opacity-10
h4.modal-title.text-primary.mb-0
i.bi.bi-arrow-left-right.me-2
| Create Notification Route
button.btn-close[type="button" data-bs-dismiss="modal" aria-label="Close"]
.modal-body
.row.g-3
/ Left column: form fields
.col-lg-8
/ Step 1: Source Selection
.mb-4
h5.fw-medium.mb-3 Where are the notifications coming from?
.row.g-3
.col-md-6
.card.border-2.selectable-card[data-route-new-target="sourceAny"]
.card-body.text-center.py-3
i.bi.bi-globe.text-info.fs-3.mb-2
h6.mb-1.text-info Any Server
small.text-muted.mb-3.d-block Route from all servers
button.btn.btn-outline-info.btn-sm.w-100[
type="button"
data-id="any"
data-action="click->route-new#onSourceCardChanged"
]
| Select
.col-md-6
.card.border-2.selectable-card[data-route-new-target="sourceCustom"]
.card-body.text-center.py-3
i.bi.bi-server.text-success.fs-3.mb-2
h6.mb-1.text-success Specific Servers
small.text-muted.mb-3.d-block Choose which servers
button.btn.btn-outline-success.btn-sm.w-100[
type="button"
data-id="custom"
data-action="click->route-new#onSourceCardChanged"
]
| Select
/ Server Selection (shown when specific is selected)
.mt-3.d-none[data-route-new-target="sourceSelect"]
= label_tag "servers", class: "form-label fw-medium"
i.bi.bi-server.text-success.me-2
| Select Servers
= select_tag "servers",
[],
class: "form-select",
multiple: true,
data: { \
controller: "slim-select",
slim_select_data_value: server_select_data,
slim_select_placeholder_value: "Choose servers...",
slim_select_allow_deselect_value: true,
route_new_target: "selectedServers",
action: [ \
slim_select_stimulus_actions("route-new"),
"change->route-new#onSelectedServerChanged",
].join(" "),
}
small.form-text.text-muted.mt-1 Select one or more servers to route notifications from
/ Step 2: Notification Types
.mb-4
h5.fw-medium.mb-3 Which notification types?
.row.g-3
.col-md-3.col-6
.card.border-2.selectable-card[data-route-new-target="presetEverything"]
.card-body.text-center.py-3
i.bi.bi-bell-fill.text-primary.fs-4.mb-2
h6.small.mb-0.text-primary Everything
button.btn.btn-outline-primary.btn-sm.w-100.mt-2[
type="button"
data-id="everything"
data-action="click->route-new#onPresetCardChanged"
]
| Select
.col-md-3.col-6
.card.border-2.selectable-card[data-route-new-target="presetRaid"]
.card-body.text-center.py-3
i.bi.bi-shield-exclamation.text-danger.fs-4.mb-2
h6.small.mb-0.text-danger Raids
button.btn.btn-outline-danger.btn-sm.w-100.mt-2[
type="button"
data-id="raid"
data-action="click->route-new#onPresetCardChanged"
]
| Select
.col-md-3.col-6
.card.border-2.selectable-card[data-route-new-target="presetMoney"]
.card-body.text-center.py-3
i.bi.bi-currency-dollar.text-success.fs-4.mb-2
h6.small.mb-0.text-success Money
button.btn.btn-outline-success.btn-sm.w-100.mt-2[
type="button"
data-id="money"
data-action="click->route-new#onPresetCardChanged"
]
| Select
.col-md-3.col-6
.card.border-2.selectable-card[data-route-new-target="presetCustom"]
.card-body.text-center.py-3
i.bi.bi-ui-checks.text-info.fs-4.mb-2
h6.small.mb-0.text-info Pick & Choose
button.btn.btn-outline-info.btn-sm.w-100.mt-2[
type="button"
data-id="custom"
data-action="click->route-new#onPresetCardChanged"
]
| Select
/ Custom Type Selection (shown when custom is selected)
.mt-3.d-none[data-route-new-target="typeSelect"]
= label_tag "notification_types", class: "form-label fw-medium"
i.bi.bi-list-check.text-info.me-2
| Select Notification Types
= select_tag "notification_types",
[],
class: "form-select",
multiple: true,
data: { \
controller: "slim-select",
slim_select_data_value: notification_type_select_data,
slim_select_placeholder_value: "Choose notification types...",
slim_select_allow_deselect_value: true,
route_new_target: "selectedTypes",
action: [ \
slim_select_stimulus_actions("route-new"),
"change->route-new#onTypesChanged",
].join(" "),
}
small.form-text.text-muted.mt-1 Pick specific notification types to route
/ Step 3: Destination
.mb-0
h5.fw-medium.mb-3 Where should notifications go?
/ Community Selection
.mb-3
= label_tag "community", class: "form-label fw-medium"
i.bi.bi-discord.text-primary.me-2
| Discord Community
= select_tag "community",
[],
class: "form-select",
data: { \
controller: "slim-select",
slim_select_data_value: community_select_data,
slim_select_placeholder_value: "Choose a community...",
slim_select_allow_deselect_value: true,
slim_select_close_on_select_value: true,
route_new_target: "selectedCommunity",
action: [ \
slim_select_stimulus_actions("route-new"),
"change->route-new#onCommunityChanged",
].join(" "),
}
small.form-text.text-muted.mt-1 Select the Discord server to route notifications to
/ Channel Selection
.mb-0
= label_tag "channel", class: "form-label fw-medium"
i.bi.bi-hash.text-info.me-2
| Notification Channel
= select_tag "channel",
[],
class: "form-select",
data: { \
controller: "slim-select",
slim_select_placeholder_value: "Select a channel...",
slim_select_allow_deselect_value: true,
slim_select_close_on_select_value: true,
route_new_target: "selectedChannel",
action: [ \
slim_select_stimulus_actions("route-new"),
"change->route-new#onChannelChanged",
].join(" "),
}
small.form-text.text-muted.mt-1 Choose which channel will receive the notifications
/ Right column: info cards
.col-lg-4
div.w-100.mt-4.pt-3
.card.border-info.bg-info.bg-opacity-10.mb-3
.card-body
h6.text-info.mb-2
i.bi.bi-info-circle.me-2
| Approval Required
p.small.mb-0
| A community admin must approve this route before notifications start flowing.
.card.border-success.bg-success.bg-opacity-10
.card-body
h6.text-success.mb-2
i.bi.bi-people-fill.me-2
| Team Notifications
p.small.mb-0
|> Want your friends notified too? They just need to create the
strong same route
|. When multiple users share a route, ESM automatically tags everyone in one message.
/ Preview Card (full width)
.card.bg-secondary.bg-opacity-10.border-secondary.mt-3
.card-header.py-2
h6.mb-0.text-light
i.bi.bi-eye.me-2
| Route Preview
.card-body.py-3
/ Inline flow visualization
.row.mb-3
.col-auto
small.text-muted.fw-medium.d-block.mb-2 FROM
.d-flex.gap-2[data-route-new-target="previewSelectedServers"]
.col-auto.d-flex.align-items-center.mt-4.pt-1
i.bi.bi-arrow-right.text-primary
.col
small.text-muted.fw-medium.d-block.mb-1 TO
span[data-route-new-target="previewTo"]
/ Types inline
small.text-muted.fw-medium.d-block.mb-1 TYPES
.d-flex.align-items-center.gap-2.flex-wrap[data-route-new-target="previewSelectedTypes"]
= form_with url: users_notification_routes_path,
method: :post,
data: {route_new_target: "form", turbo: false},
class: "d-none"
span[data-routes-new-storage]
.modal-footer.border-top
/ Mobile
.row.g-2.w-100.d-flex.d-lg-none
.col-6
button.btn.btn-outline-secondary.w-100[type="button" data-bs-dismiss="modal"] Cancel
.col-6
= button_tag class: "btn btn-success w-100",
data: {action: "click->route-new#onCreateClicked"}
i.bi.bi-plus-circle.me-2
| Create Route
/ Desktop
.d-none.d-lg-flex.align-items-center.justify-content-between.w-100
div
.d-flex.gap-2
button.btn.btn-outline-secondary[type="button" data-bs-dismiss="modal"] Cancel
= button_tag class: "btn btn-success ms-2",
data: {action: "click->route-new#onCreateClicked"}
i.bi.bi-plus-circle.me-2
| Create Route