Pick agents from a grid of their icons (running or all), type the text, send. The page posts the names and the text to the controller and shows what happened to each agent, with a retry that selects just the ones that failed. The selection rules and the controller's answer are read by plain functions with tests.
166 lines
3.2 KiB
CSS
166 lines
3.2 KiB
CSS
/* <BroadcastPage>: the agent picker over the message box, then the per-agent
|
|
result. One column; the grid wraps to however many icons fit. */
|
|
.ui-broadcast {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1em;
|
|
}
|
|
.ui-broadcast-bar {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 0.5em 1em;
|
|
}
|
|
/* Same segmented pair as the agents page's view switcher. */
|
|
.ui-broadcast-filter {
|
|
display: inline-flex;
|
|
border: 1px solid var(--border);
|
|
border-radius: 0.4em;
|
|
overflow: hidden;
|
|
}
|
|
.ui-broadcast-filter button {
|
|
border: none;
|
|
background: none;
|
|
color: var(--muted);
|
|
padding: 0.45em 0.75em;
|
|
font: inherit;
|
|
font-size: 0.9em;
|
|
cursor: pointer;
|
|
}
|
|
.ui-broadcast-filter button + button {
|
|
border-left: 1px solid var(--border);
|
|
}
|
|
.ui-broadcast-filter button.active {
|
|
background: var(--bg-elev);
|
|
color: var(--fg);
|
|
}
|
|
.ui-broadcast-filter button:not(.active):hover {
|
|
color: var(--fg);
|
|
}
|
|
.ui-broadcast-link {
|
|
border: none;
|
|
background: none;
|
|
padding: 0.2em 0;
|
|
color: var(--blue);
|
|
font: inherit;
|
|
font-size: 0.9em;
|
|
cursor: pointer;
|
|
text-decoration: underline;
|
|
}
|
|
.ui-broadcast-link:disabled {
|
|
color: var(--muted);
|
|
text-decoration: none;
|
|
cursor: default;
|
|
}
|
|
.ui-broadcast-count {
|
|
margin-left: auto;
|
|
color: var(--muted);
|
|
font-size: 0.9em;
|
|
}
|
|
.ui-broadcast-empty {
|
|
color: var(--muted);
|
|
text-align: center;
|
|
padding: 1.25em 0.75em;
|
|
margin: 0;
|
|
}
|
|
|
|
/* The picker: each agent a labelled checkbox card, icon over name. */
|
|
.ui-broadcast-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(8em, 1fr));
|
|
gap: 0.6em;
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
.ui-broadcast-agent {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 0.35em;
|
|
padding: 0.7em 0.5em 0.6em;
|
|
border: 1px solid var(--border);
|
|
border-radius: 0.5em;
|
|
background: var(--bg);
|
|
cursor: pointer;
|
|
}
|
|
.ui-broadcast-agent:hover {
|
|
border-color: var(--muted);
|
|
}
|
|
.ui-broadcast-agent-on {
|
|
border-color: var(--purple);
|
|
background: var(--bg-elev);
|
|
}
|
|
.ui-broadcast-agent:focus-within {
|
|
outline: 2px solid var(--purple);
|
|
outline-offset: 2px;
|
|
}
|
|
.ui-broadcast-check {
|
|
position: absolute;
|
|
top: 0.5em;
|
|
left: 0.5em;
|
|
margin: 0;
|
|
}
|
|
.ui-broadcast-name {
|
|
max-width: 100%;
|
|
overflow-wrap: anywhere;
|
|
text-align: center;
|
|
}
|
|
.ui-broadcast-state {
|
|
color: var(--muted);
|
|
font-size: 0.8em;
|
|
}
|
|
.ui-broadcast-state-up {
|
|
color: var(--green);
|
|
}
|
|
|
|
.ui-broadcast-send {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
gap: 0.75em;
|
|
}
|
|
|
|
.ui-broadcast-cap {
|
|
color: var(--red);
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
/* What came back, one line per agent. */
|
|
.ui-broadcast-result {
|
|
margin-top: 1em;
|
|
}
|
|
.ui-broadcast-summary {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: baseline;
|
|
gap: 0.5em 1em;
|
|
margin: 0 0 0.5em;
|
|
}
|
|
.ui-broadcast-outcomes {
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.35em;
|
|
}
|
|
.ui-broadcast-outcomes li {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.6em;
|
|
}
|
|
.ui-broadcast-outcome-name {
|
|
font-weight: 600;
|
|
}
|
|
.ui-broadcast-ok {
|
|
color: var(--green);
|
|
}
|
|
.ui-broadcast-fail {
|
|
color: var(--red);
|
|
}
|
|
.ui-broadcast-ok .ui-broadcast-outcome-name,
|
|
.ui-broadcast-fail .ui-broadcast-outcome-name {
|
|
color: var(--fg);
|
|
}
|