use crate::reply::roles::RoleRow;
use crate::ui::{Model, theme};
pub const OPEN: &str = "tune the roles…";
pub const CLOSE: &str = "done";
pub const HEADING: &str = "role tuning";
pub const NOT_ANSWERED: &str = "waiting to hear what this wall's roles are";
pub const NO_ROLES: &str = "this workspace's config declares no role";
pub const PRIORITY: &str = "priority";
pub const ASSIGN: &str = "model…";
pub const SET: &str = "set";
pub const CANCEL: &str = "cancel";
pub const PROVIDER_HINT: &str = "provider row";
pub const MODEL_HINT: &str = "model id";
pub fn render(ui: &mut egui::Ui, model: &mut Model) -> bool {
if model.tuning.is_none() {
return false;
}
ui.heading(HEADING);
if let Some(aim) = model.aim.clone() {
ui.label(format!("on {} — {}", aim.address, aim.channel));
}
ui.horizontal_wrapped(|ui| {
if ui.button(CLOSE).clicked() {
model.close_tuning();
}
});
ui.separator();
match model.roles.clone() {
None => {
ui.label(NOT_ANSWERED);
}
Some(rows) if rows.is_empty() => {
ui.label(NO_ROLES);
}
Some(rows) => {
egui::ScrollArea::vertical()
.id_salt(HEADING)
.auto_shrink(false)
.show(ui, |ui| {
for row in &rows {
role(ui, model, row);
}
});
}
}
true
}
fn role(ui: &mut egui::Ui, model: &mut Model, row: &RoleRow) {
ui.separator();
ui.label(row.role.clone());
ui.colored_label(
theme::tone_ink(&crate::reply::convs::Tone::Weak),
row.runs_on(),
);
ui.horizontal_wrapped(|ui| {
for level in crate::verbs::tuning::levels() {
let chosen = row.effort == level;
let seat = ui.selectable_label(chosen, crate::verbs::tuning::word(level.as_ref()));
crate::ui::act::tag(&seat, &[crate::verbs::EFFORT]);
if seat.clicked() {
model.post_effort(&row.role, level.clone());
}
}
let mut on = row.priority;
let lane = ui.checkbox(&mut on, PRIORITY);
crate::ui::act::tag(&lane, &[crate::verbs::PRIORITY]);
if lane.clicked() {
model.post_priority(&row.role, on);
}
});
if let Some(said) = unseated(row) {
ui.colored_label(theme::NOTICE, said);
}
assignment(ui, model, row);
}
pub fn unseated(row: &RoleRow) -> Option<String> {
let known = crate::verbs::tuning::levels().contains(&row.effort);
let level = row.effort.clone()?;
(!known).then(|| format!("asking for {level:?}, which this seat has no seat for"))
}
fn assignment(ui: &mut egui::Ui, model: &mut Model, row: &RoleRow) {
if model.editing(&row.role).is_none() {
if ui.button(ASSIGN).clicked() {
model.edit_assignment(row);
}
return;
}
let mut ready = false;
if let Some(edit) = model.draft_assignment() {
ready = edit.ready();
ui.horizontal_wrapped(|ui| {
ui.add(egui::TextEdit::singleline(&mut edit.provider).hint_text(PROVIDER_HINT));
ui.add(egui::TextEdit::singleline(&mut edit.model).hint_text(MODEL_HINT));
});
}
ui.horizontal_wrapped(|ui| {
let set = ui.add_enabled(ready, egui::Button::new(SET));
crate::ui::act::tag(&set, &[crate::verbs::MODEL.word]);
if set.clicked() {
model.post_assignment();
}
if ui.button(CANCEL).clicked() {
model.cancel_assignment();
}
});
}
#[cfg(test)]
mod tests;