|
@@ -37,7 +37,102 @@ impl RibbonUI {
|
|
|
Some(self.active_tab.clone())
|
|
Some(self.active_tab.clone())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub fn show(&mut self, _ctx: &egui::Context, ui: &mut egui::Ui) -> Option<String> {
|
|
|
|
|
|
|
+ pub fn check_permission(permissions: Option<&serde_json::Value>, key: &str) -> bool {
|
|
|
|
|
+ if let Some(perms) = permissions {
|
|
|
|
|
+ // If permissions is a boolean map (legacy/simple), handle it
|
|
|
|
|
+ if let Some(val) = perms.get(key) {
|
|
|
|
|
+ if let Some(b) = val.as_bool() {
|
|
|
|
|
+ return b;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // If permissions is a table map (RBAC), map key to table permission
|
|
|
|
|
+ // Helper to check table permission
|
|
|
|
|
+ let check_table = |table: &str, require_write: bool| -> bool {
|
|
|
|
|
+ if let Some(p_val) = perms.get(table) {
|
|
|
|
|
+ if let Some(p_str) = p_val.as_str() {
|
|
|
|
|
+ if require_write {
|
|
|
|
|
+ return p_str == "w" || p_str == "rw";
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return p_str == "r" || p_str == "rw";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ false
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ match key {
|
|
|
|
|
+ // Views
|
|
|
|
|
+ "view_dashboard" => true, // Everyone can see dashboard
|
|
|
|
|
+ "view_inventory" => check_table("assets", false),
|
|
|
|
|
+ "view_categories" => check_table("categories", false),
|
|
|
|
|
+ "view_zones" => check_table("zones", false),
|
|
|
|
|
+ "view_borrowing" => check_table("assets", false), // Needs assets read
|
|
|
|
|
+ "view_audits" => check_table("audit_tasks", false) || check_table("physical_audits", false),
|
|
|
|
|
+ "view_suppliers" => check_table("suppliers", false),
|
|
|
|
|
+ "view_issues" => check_table("issue_tracker", false),
|
|
|
|
|
+ "view_printers" => check_table("printer_settings", false),
|
|
|
|
|
+ "view_label_templates" => check_table("label_templates", false),
|
|
|
|
|
+ "view_item_templates" => check_table("templates", false),
|
|
|
|
|
+
|
|
|
|
|
+ // Inventory Actions
|
|
|
|
|
+ "create_asset" => check_table("assets", true),
|
|
|
|
|
+ "edit_asset" => check_table("assets", true),
|
|
|
|
|
+ "delete_asset" => check_table("assets", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Borrowing Actions
|
|
|
|
|
+ "checkout_asset" => check_table("assets", true), // Modifies asset status
|
|
|
|
|
+ "return_asset" => check_table("assets", true),
|
|
|
|
|
+ "create_borrower" => check_table("borrowers", true),
|
|
|
|
|
+ "edit_borrower" => check_table("borrowers", true),
|
|
|
|
|
+ "delete_borrower" => check_table("borrowers", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Audit Actions
|
|
|
|
|
+ "create_audit" => check_table("physical_audits", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Supplier Actions
|
|
|
|
|
+ "create_supplier" => check_table("suppliers", true),
|
|
|
|
|
+ "edit_supplier" => check_table("suppliers", true),
|
|
|
|
|
+ "delete_supplier" => check_table("suppliers", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Issue Actions
|
|
|
|
|
+ "report_issue" => check_table("issue_tracker", true),
|
|
|
|
|
+ "view_issue" => check_table("issue_tracker", false),
|
|
|
|
|
+ "edit_issue" => check_table("issue_tracker", true),
|
|
|
|
|
+ "delete_issue" => check_table("issue_tracker", true),
|
|
|
|
|
+ "resolve_issue" => check_table("issue_tracker", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Category Actions
|
|
|
|
|
+ "create_category" => check_table("categories", true),
|
|
|
|
|
+ "edit_category" => check_table("categories", true),
|
|
|
|
|
+ "delete_category" => check_table("categories", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Zone Actions
|
|
|
|
|
+ "create_zone" => check_table("zones", true),
|
|
|
|
|
+ "edit_zone" => check_table("zones", true),
|
|
|
|
|
+ "delete_zone" => check_table("zones", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Printer Actions
|
|
|
|
|
+ "create_printer" => check_table("printer_settings", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Label Template Actions
|
|
|
|
|
+ "create_label_template" => check_table("label_templates", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Template Actions
|
|
|
|
|
+ "create_template" => check_table("templates", true),
|
|
|
|
|
+ "edit_template" => check_table("templates", true),
|
|
|
|
|
+ "delete_template" => check_table("templates", true),
|
|
|
|
|
+
|
|
|
|
|
+ // Fallback
|
|
|
|
|
+ _ => false,
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // If no permissions provided (legacy/dev), allow everything
|
|
|
|
|
+ true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn show(&mut self, _ctx: &egui::Context, ui: &mut egui::Ui, permissions: Option<&serde_json::Value>) -> Option<String> {
|
|
|
// Clear one-shot trigger flags from previous frame so clicks only fire once
|
|
// Clear one-shot trigger flags from previous frame so clicks only fire once
|
|
|
// NOTE: inventory_filter_changed and templates_filter_changed are NOT cleared here - they're cleared by their views after processing
|
|
// NOTE: inventory_filter_changed and templates_filter_changed are NOT cleared here - they're cleared by their views after processing
|
|
|
for key in [
|
|
for key in [
|
|
@@ -64,27 +159,30 @@ impl RibbonUI {
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
// Tab headers row
|
|
// Tab headers row
|
|
|
ui.horizontal(|ui| {
|
|
ui.horizontal(|ui| {
|
|
|
- let tabs = vec![
|
|
|
|
|
- "Dashboard",
|
|
|
|
|
- "Inventory",
|
|
|
|
|
- "Categories",
|
|
|
|
|
- "Zones",
|
|
|
|
|
- "Borrowing",
|
|
|
|
|
- "Audits",
|
|
|
|
|
- "Suppliers",
|
|
|
|
|
- "Issues",
|
|
|
|
|
- "Printers",
|
|
|
|
|
- "Label Templates",
|
|
|
|
|
- "Item Templates",
|
|
|
|
|
|
|
+ let all_tabs = vec![
|
|
|
|
|
+ ("Dashboard", "view_dashboard"),
|
|
|
|
|
+ ("Inventory", "view_inventory"),
|
|
|
|
|
+ ("Categories", "view_categories"),
|
|
|
|
|
+ ("Zones", "view_zones"),
|
|
|
|
|
+ ("Borrowing", "view_borrowing"),
|
|
|
|
|
+ ("Audits", "view_audits"),
|
|
|
|
|
+ ("Suppliers", "view_suppliers"),
|
|
|
|
|
+ ("Issues", "view_issues"),
|
|
|
|
|
+ ("Printers", "view_printers"),
|
|
|
|
|
+ ("Label Templates", "view_label_templates"),
|
|
|
|
|
+ ("Item Templates", "view_item_templates"),
|
|
|
];
|
|
];
|
|
|
- for tab in &tabs {
|
|
|
|
|
- if ui.selectable_label(self.active_tab == *tab, *tab).clicked() {
|
|
|
|
|
- self.active_tab = tab.to_string();
|
|
|
|
|
- // Update filter columns based on the active tab
|
|
|
|
|
- match *tab {
|
|
|
|
|
- "Zones" => self.filter_builder.set_columns_for_context("zones"),
|
|
|
|
|
- "Inventory" => self.filter_builder.set_columns_for_context("assets"),
|
|
|
|
|
- _ => {}
|
|
|
|
|
|
|
+
|
|
|
|
|
+ for (tab, perm) in &all_tabs {
|
|
|
|
|
+ if Self::check_permission(permissions, perm) {
|
|
|
|
|
+ if ui.selectable_label(self.active_tab == *tab, *tab).clicked() {
|
|
|
|
|
+ self.active_tab = tab.to_string();
|
|
|
|
|
+ // Update filter columns based on the active tab
|
|
|
|
|
+ match *tab {
|
|
|
|
|
+ "Zones" => self.filter_builder.set_columns_for_context("zones"),
|
|
|
|
|
+ "Inventory" => self.filter_builder.set_columns_for_context("assets"),
|
|
|
|
|
+ _ => {}
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -100,17 +198,17 @@ impl RibbonUI {
|
|
|
|ui| {
|
|
|ui| {
|
|
|
egui::ScrollArea::horizontal().show(ui, |ui| {
|
|
egui::ScrollArea::horizontal().show(ui, |ui| {
|
|
|
ui.horizontal(|ui| match self.active_tab.as_str() {
|
|
ui.horizontal(|ui| match self.active_tab.as_str() {
|
|
|
- "Dashboard" => self.show_dashboard_tab(ui, ribbon_height),
|
|
|
|
|
- "Inventory" => self.show_inventory_tab(ui, ribbon_height),
|
|
|
|
|
- "Categories" => self.show_categories_tab(ui, ribbon_height),
|
|
|
|
|
- "Zones" => self.show_zones_tab(ui, ribbon_height),
|
|
|
|
|
- "Borrowing" => self.show_borrowing_tab(ui, ribbon_height),
|
|
|
|
|
- "Audits" => self.show_audits_tab(ui, ribbon_height),
|
|
|
|
|
- "Item Templates" => self.show_templates_tab(ui, ribbon_height),
|
|
|
|
|
- "Suppliers" => self.show_suppliers_tab(ui, ribbon_height),
|
|
|
|
|
- "Issues" => self.show_issues_tab(ui, ribbon_height),
|
|
|
|
|
- "Printers" => self.show_printers_tab(ui, ribbon_height),
|
|
|
|
|
- "Label Templates" => self.show_label_templates_tab(ui, ribbon_height),
|
|
|
|
|
|
|
+ "Dashboard" => self.show_dashboard_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Inventory" => self.show_inventory_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Categories" => self.show_categories_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Zones" => self.show_zones_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Borrowing" => self.show_borrowing_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Audits" => self.show_audits_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Item Templates" => self.show_templates_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Suppliers" => self.show_suppliers_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Issues" => self.show_issues_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Printers" => self.show_printers_tab(ui, ribbon_height, permissions),
|
|
|
|
|
+ "Label Templates" => self.show_label_templates_tab(ui, ribbon_height, permissions),
|
|
|
_ => {}
|
|
_ => {}
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
@@ -172,7 +270,7 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_dashboard_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_dashboard_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, _permissions: Option<&serde_json::Value>) {
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
@@ -207,7 +305,7 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_inventory_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_inventory_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
@@ -242,42 +340,54 @@ impl RibbonUI {
|
|
|
let idx = col * rows + row;
|
|
let idx = col * rows + row;
|
|
|
let w = col_widths[col];
|
|
let w = col_widths[col];
|
|
|
let button = egui::Button::new(labels[idx]);
|
|
let button = egui::Button::new(labels[idx]);
|
|
|
- let clicked = ui.add_sized([w, row_height], button).clicked();
|
|
|
|
|
- if clicked {
|
|
|
|
|
- // If user holds Alt while clicking Edit, trigger Advanced Edit instead of Easy
|
|
|
|
|
- let alt_held = ui.input(|i| i.modifiers.alt);
|
|
|
|
|
- match idx {
|
|
|
|
|
- 0 => {
|
|
|
|
|
- self.checkboxes
|
|
|
|
|
- .insert("inventory_action_add".to_string(), true);
|
|
|
|
|
- }
|
|
|
|
|
- 1 => {
|
|
|
|
|
- if alt_held {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ let enabled = match idx {
|
|
|
|
|
+ 0 => Self::check_permission(permissions, "create_asset"),
|
|
|
|
|
+ 1 => Self::check_permission(permissions, "edit_asset"),
|
|
|
|
|
+ 2 => Self::check_permission(permissions, "delete_asset"),
|
|
|
|
|
+ _ => true,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ if enabled {
|
|
|
|
|
+ let clicked = ui.add_sized([w, row_height], button).clicked();
|
|
|
|
|
+ if clicked {
|
|
|
|
|
+ // If user holds Alt while clicking Edit, trigger Advanced Edit instead of Easy
|
|
|
|
|
+ let alt_held = ui.input(|i| i.modifiers.alt);
|
|
|
|
|
+ match idx {
|
|
|
|
|
+ 0 => {
|
|
|
|
|
+ self.checkboxes
|
|
|
|
|
+ .insert("inventory_action_add".to_string(), true);
|
|
|
|
|
+ }
|
|
|
|
|
+ 1 => {
|
|
|
|
|
+ if alt_held {
|
|
|
|
|
+ self.checkboxes.insert(
|
|
|
|
|
+ "inventory_action_edit_adv".to_string(),
|
|
|
|
|
+ true,
|
|
|
|
|
+ );
|
|
|
|
|
+ } else {
|
|
|
|
|
+ self.checkboxes.insert(
|
|
|
|
|
+ "inventory_action_edit_easy".to_string(),
|
|
|
|
|
+ true,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ 2 => {
|
|
|
self.checkboxes.insert(
|
|
self.checkboxes.insert(
|
|
|
- "inventory_action_edit_adv".to_string(),
|
|
|
|
|
|
|
+ "inventory_action_delete".to_string(),
|
|
|
true,
|
|
true,
|
|
|
);
|
|
);
|
|
|
- } else {
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ 3 => {
|
|
|
self.checkboxes.insert(
|
|
self.checkboxes.insert(
|
|
|
- "inventory_action_edit_easy".to_string(),
|
|
|
|
|
|
|
+ "inventory_action_print_label".to_string(),
|
|
|
true,
|
|
true,
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
+ _ => {}
|
|
|
}
|
|
}
|
|
|
- 2 => {
|
|
|
|
|
- self.checkboxes.insert(
|
|
|
|
|
- "inventory_action_delete".to_string(),
|
|
|
|
|
- true,
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
- 3 => {
|
|
|
|
|
- self.checkboxes.insert(
|
|
|
|
|
- "inventory_action_print_label".to_string(),
|
|
|
|
|
- true,
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
- _ => {}
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ui.allocate_space(egui::vec2(w, row_height));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
ui.end_row();
|
|
ui.end_row();
|
|
@@ -341,51 +451,53 @@ impl RibbonUI {
|
|
|
let w2 = 8.0 * "Add from...".len() as f32 + pad_x * 2.0;
|
|
let w2 = 8.0 * "Add from...".len() as f32 + pad_x * 2.0;
|
|
|
let w = w1.max(w2).max(130.0);
|
|
let w = w1.max(w2).max(130.0);
|
|
|
|
|
|
|
|
- if ui
|
|
|
|
|
- .add_sized([w, 24.0], egui::Button::new("Inventarize Room"))
|
|
|
|
|
- .clicked()
|
|
|
|
|
- {
|
|
|
|
|
- self.checkboxes
|
|
|
|
|
- .insert("inventory_quick_inventarize_room".to_string(), true);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if Self::check_permission(permissions, "create_asset") {
|
|
|
|
|
+ if ui
|
|
|
|
|
+ .add_sized([w, 24.0], egui::Button::new("Inventarize Room"))
|
|
|
|
|
+ .clicked()
|
|
|
|
|
+ {
|
|
|
|
|
+ self.checkboxes
|
|
|
|
|
+ .insert("inventory_quick_inventarize_room".to_string(), true);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // Use a fixed-width ComboBox as a dropdown to ensure equal width
|
|
|
|
|
- egui::ComboBox::from_id_salt("inventory_add_from_combo")
|
|
|
|
|
- .width(w)
|
|
|
|
|
- .selected_text("Add from...")
|
|
|
|
|
- .show_ui(ui, |ui| {
|
|
|
|
|
- if ui.selectable_label(false, "Add from Template").clicked() {
|
|
|
|
|
- self.checkboxes.insert(
|
|
|
|
|
- "inventory_add_from_template_single".to_string(),
|
|
|
|
|
- true,
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
- if ui
|
|
|
|
|
- .selectable_label(false, "Add Multiple from Template")
|
|
|
|
|
- .clicked()
|
|
|
|
|
- {
|
|
|
|
|
- self.checkboxes.insert(
|
|
|
|
|
- "inventory_add_from_template_multiple".to_string(),
|
|
|
|
|
- true,
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
- if ui
|
|
|
|
|
- .selectable_label(false, "Add using Another Item")
|
|
|
|
|
- .clicked()
|
|
|
|
|
- {
|
|
|
|
|
- self.checkboxes
|
|
|
|
|
- .insert("inventory_add_from_item_single".to_string(), true);
|
|
|
|
|
- }
|
|
|
|
|
- if ui
|
|
|
|
|
- .selectable_label(false, "Add Multiple from Another Item")
|
|
|
|
|
- .clicked()
|
|
|
|
|
- {
|
|
|
|
|
- self.checkboxes.insert(
|
|
|
|
|
- "inventory_add_from_item_multiple".to_string(),
|
|
|
|
|
- true,
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ // Use a fixed-width ComboBox as a dropdown to ensure equal width
|
|
|
|
|
+ egui::ComboBox::from_id_salt("inventory_add_from_combo")
|
|
|
|
|
+ .width(w)
|
|
|
|
|
+ .selected_text("Add from...")
|
|
|
|
|
+ .show_ui(ui, |ui| {
|
|
|
|
|
+ if ui.selectable_label(false, "Add from Template").clicked() {
|
|
|
|
|
+ self.checkboxes.insert(
|
|
|
|
|
+ "inventory_add_from_template_single".to_string(),
|
|
|
|
|
+ true,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ if ui
|
|
|
|
|
+ .selectable_label(false, "Add Multiple from Template")
|
|
|
|
|
+ .clicked()
|
|
|
|
|
+ {
|
|
|
|
|
+ self.checkboxes.insert(
|
|
|
|
|
+ "inventory_add_from_template_multiple".to_string(),
|
|
|
|
|
+ true,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ if ui
|
|
|
|
|
+ .selectable_label(false, "Add using Another Item")
|
|
|
|
|
+ .clicked()
|
|
|
|
|
+ {
|
|
|
|
|
+ self.checkboxes
|
|
|
|
|
+ .insert("inventory_add_from_item_single".to_string(), true);
|
|
|
|
|
+ }
|
|
|
|
|
+ if ui
|
|
|
|
|
+ .selectable_label(false, "Add Multiple from Another Item")
|
|
|
|
|
+ .clicked()
|
|
|
|
|
+ {
|
|
|
|
|
+ self.checkboxes.insert(
|
|
|
|
|
+ "inventory_add_from_item_multiple".to_string(),
|
|
|
|
|
+ true,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
@@ -481,7 +593,7 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_categories_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_categories_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
// Clear one-shot action triggers from previous frame
|
|
// Clear one-shot action triggers from previous frame
|
|
|
for key in [
|
|
for key in [
|
|
|
"categories_refresh",
|
|
"categories_refresh",
|
|
@@ -497,25 +609,35 @@ impl RibbonUI {
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
ui.label("Actions");
|
|
ui.label("Actions");
|
|
|
// Match Inventory layout: [Add, Edit, Delete, Refresh] (Refresh where Inventory has Print)
|
|
// Match Inventory layout: [Add, Edit, Delete, Refresh] (Refresh where Inventory has Print)
|
|
|
- let items = vec![
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ let mut items = Vec::new();
|
|
|
|
|
+
|
|
|
|
|
+ if Self::check_permission(permissions, "create_category") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PLUS, "Add Category"),
|
|
format!("{} {}", icons::PLUS, "Add Category"),
|
|
|
"categories_add",
|
|
"categories_add",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "edit_category") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PENCIL, "Edit Category"),
|
|
format!("{} {}", icons::PENCIL, "Edit Category"),
|
|
|
"categories_edit",
|
|
"categories_edit",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "delete_category") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::TRASH, "Delete Category"),
|
|
format!("{} {}", icons::TRASH, "Delete Category"),
|
|
|
"categories_delete",
|
|
"categories_delete",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
- format!("{} {}", icons::ARROWS_CLOCKWISE, "Refresh"),
|
|
|
|
|
- "categories_refresh",
|
|
|
|
|
- ),
|
|
|
|
|
- ];
|
|
|
|
|
- self.render_actions_grid_with_keys(ui, "categories_actions_grid", &items);
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ items.push((
|
|
|
|
|
+ format!("{} {}", icons::ARROWS_CLOCKWISE, "Refresh"),
|
|
|
|
|
+ "categories_refresh",
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ // Convert to slice of references for the helper
|
|
|
|
|
+ let items_refs: Vec<(String, &str)> = items.iter().map(|(s, k)| (s.clone(), *k)).collect();
|
|
|
|
|
+ self.render_actions_grid_with_keys(ui, "categories_actions_grid", &items_refs);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -536,7 +658,7 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_zones_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_zones_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
// Clear one-shot action triggers from previous frame
|
|
// Clear one-shot action triggers from previous frame
|
|
|
for key in [
|
|
for key in [
|
|
|
"zones_action_add",
|
|
"zones_action_add",
|
|
@@ -550,17 +672,23 @@ impl RibbonUI {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
ui.label("Actions");
|
|
ui.label("Actions");
|
|
|
- let items = vec![
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ let mut items = Vec::new();
|
|
|
|
|
+
|
|
|
|
|
+ if Self::check_permission(permissions, "create_zone") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PLUS, "Add Zone"),
|
|
format!("{} {}", icons::PLUS, "Add Zone"),
|
|
|
"zones_action_add",
|
|
"zones_action_add",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "edit_zone") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PENCIL, "Edit Zone"),
|
|
format!("{} {}", icons::PENCIL, "Edit Zone"),
|
|
|
"zones_action_edit",
|
|
"zones_action_edit",
|
|
|
- ),
|
|
|
|
|
- ];
|
|
|
|
|
- self.render_actions_grid_with_keys(ui, "zones_actions_grid", &items);
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let items_refs: Vec<(String, &str)> = items.iter().map(|(s, k)| (s.clone(), *k)).collect();
|
|
|
|
|
+ self.render_actions_grid_with_keys(ui, "zones_actions_grid", &items_refs);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
@@ -612,7 +740,7 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_borrowing_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_borrowing_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
// Clear one-shot action triggers from previous frame
|
|
// Clear one-shot action triggers from previous frame
|
|
|
for key in [
|
|
for key in [
|
|
|
"borrowing_action_checkout",
|
|
"borrowing_action_checkout",
|
|
@@ -627,25 +755,34 @@ impl RibbonUI {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
ui.label("Actions");
|
|
ui.label("Actions");
|
|
|
- let items = vec![
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ let mut items = Vec::new();
|
|
|
|
|
+
|
|
|
|
|
+ if Self::check_permission(permissions, "checkout_asset") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::ARROW_LEFT, "Check Out"),
|
|
format!("{} {}", icons::ARROW_LEFT, "Check Out"),
|
|
|
"borrowing_action_checkout",
|
|
"borrowing_action_checkout",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "return_asset") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::ARROW_RIGHT, "Return"),
|
|
format!("{} {}", icons::ARROW_RIGHT, "Return"),
|
|
|
"borrowing_action_return",
|
|
"borrowing_action_return",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "register_borrower") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PENCIL, "Register"),
|
|
format!("{} {}", icons::PENCIL, "Register"),
|
|
|
"borrowing_action_register",
|
|
"borrowing_action_register",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
- format!("{} {}", icons::ARROWS_CLOCKWISE, "Refresh"),
|
|
|
|
|
- "borrowing_action_refresh",
|
|
|
|
|
- ),
|
|
|
|
|
- ];
|
|
|
|
|
- self.render_actions_grid_with_keys(ui, "borrowing_actions_grid", &items);
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ items.push((
|
|
|
|
|
+ format!("{} {}", icons::ARROWS_CLOCKWISE, "Refresh"),
|
|
|
|
|
+ "borrowing_action_refresh",
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ let items_refs: Vec<(String, &str)> = items.iter().map(|(s, k)| (s.clone(), *k)).collect();
|
|
|
|
|
+ self.render_actions_grid_with_keys(ui, "borrowing_actions_grid", &items_refs);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
@@ -668,22 +805,30 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_audits_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_audits_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
ui.label("Actions");
|
|
ui.label("Actions");
|
|
|
- let items = vec![
|
|
|
|
|
- ("New Audit".to_string(), "audits_action_new"),
|
|
|
|
|
- ("View Audit".to_string(), "audits_action_view"),
|
|
|
|
|
- ("Export Report".to_string(), "audits_action_export"),
|
|
|
|
|
- ];
|
|
|
|
|
- self.render_actions_grid_with_keys(ui, "audits_actions_grid", &items);
|
|
|
|
|
|
|
+ let mut items = Vec::new();
|
|
|
|
|
+
|
|
|
|
|
+ if Self::check_permission(permissions, "create_audit") {
|
|
|
|
|
+ items.push(("New Audit".to_string(), "audits_action_new"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "view_audit") {
|
|
|
|
|
+ items.push(("View Audit".to_string(), "audits_action_view"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "export_audit") {
|
|
|
|
|
+ items.push(("Export Report".to_string(), "audits_action_export"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let items_refs: Vec<(String, &str)> = items.iter().map(|(s, k)| (s.clone(), *k)).collect();
|
|
|
|
|
+ self.render_actions_grid_with_keys(ui, "audits_actions_grid", &items_refs);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_templates_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_templates_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
// Clear one-shot action triggers from previous frame
|
|
// Clear one-shot action triggers from previous frame
|
|
|
for key in [
|
|
for key in [
|
|
|
"templates_action_new",
|
|
"templates_action_new",
|
|
@@ -697,17 +842,23 @@ impl RibbonUI {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
ui.label("Actions");
|
|
ui.label("Actions");
|
|
|
- let items = vec![
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ let mut items = Vec::new();
|
|
|
|
|
+
|
|
|
|
|
+ if Self::check_permission(permissions, "create_template") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PLUS, "Add Template"),
|
|
format!("{} {}", icons::PLUS, "Add Template"),
|
|
|
"templates_action_new",
|
|
"templates_action_new",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "edit_template") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PENCIL, "Edit Template"),
|
|
format!("{} {}", icons::PENCIL, "Edit Template"),
|
|
|
"templates_action_edit",
|
|
"templates_action_edit",
|
|
|
- ),
|
|
|
|
|
- ];
|
|
|
|
|
- self.render_actions_grid_with_keys(ui, "templates_actions_grid", &items);
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let items_refs: Vec<(String, &str)> = items.iter().map(|(s, k)| (s.clone(), *k)).collect();
|
|
|
|
|
+ self.render_actions_grid_with_keys(ui, "templates_actions_grid", &items_refs);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
// Import/Export removed for now
|
|
// Import/Export removed for now
|
|
@@ -765,17 +916,25 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_issues_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_issues_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
ui.label("Actions");
|
|
ui.label("Actions");
|
|
|
- let items = vec![
|
|
|
|
|
- ("Report Issue".to_string(), "issues_action_report"),
|
|
|
|
|
- ("View Issue".to_string(), "issues_action_view"),
|
|
|
|
|
- ("Resolve Issue".to_string(), "issues_action_resolve"),
|
|
|
|
|
- ];
|
|
|
|
|
- self.render_actions_grid_with_keys(ui, "issues_actions_grid", &items);
|
|
|
|
|
|
|
+ let mut items = Vec::new();
|
|
|
|
|
+
|
|
|
|
|
+ if Self::check_permission(permissions, "report_issue") {
|
|
|
|
|
+ items.push(("Report Issue".to_string(), "issues_action_report"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "view_issue") {
|
|
|
|
|
+ items.push(("View Issue".to_string(), "issues_action_view"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "resolve_issue") {
|
|
|
|
|
+ items.push(("Resolve Issue".to_string(), "issues_action_resolve"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let items_refs: Vec<(String, &str)> = items.iter().map(|(s, k)| (s.clone(), *k)).collect();
|
|
|
|
|
+ self.render_actions_grid_with_keys(ui, "issues_actions_grid", &items_refs);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
@@ -817,7 +976,7 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_suppliers_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_suppliers_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
for key in [
|
|
for key in [
|
|
|
"suppliers_action_new",
|
|
"suppliers_action_new",
|
|
|
"suppliers_action_edit",
|
|
"suppliers_action_edit",
|
|
@@ -830,17 +989,23 @@ impl RibbonUI {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
ui.label("Actions");
|
|
ui.label("Actions");
|
|
|
- let items = vec![
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ let mut items = Vec::new();
|
|
|
|
|
+
|
|
|
|
|
+ if Self::check_permission(permissions, "create_supplier") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PLUS, "New Supplier"),
|
|
format!("{} {}", icons::PLUS, "New Supplier"),
|
|
|
"suppliers_action_new",
|
|
"suppliers_action_new",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ if Self::check_permission(permissions, "edit_supplier") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PENCIL, "Edit Supplier"),
|
|
format!("{} {}", icons::PENCIL, "Edit Supplier"),
|
|
|
"suppliers_action_edit",
|
|
"suppliers_action_edit",
|
|
|
- ),
|
|
|
|
|
- ];
|
|
|
|
|
- self.render_actions_grid_with_keys(ui, "suppliers_actions_grid", &items);
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let items_refs: Vec<(String, &str)> = items.iter().map(|(s, k)| (s.clone(), *k)).collect();
|
|
|
|
|
+ self.render_actions_grid_with_keys(ui, "suppliers_actions_grid", &items_refs);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
@@ -860,7 +1025,7 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub fn show_printers_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ pub fn show_printers_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
// Clear one-shot action triggers from previous frame
|
|
// Clear one-shot action triggers from previous frame
|
|
|
for key in [
|
|
for key in [
|
|
|
"printers_action_add",
|
|
"printers_action_add",
|
|
@@ -875,17 +1040,22 @@ impl RibbonUI {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
ui.label("Actions");
|
|
ui.label("Actions");
|
|
|
- let items = vec![
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ let mut items = Vec::new();
|
|
|
|
|
+
|
|
|
|
|
+ if Self::check_permission(permissions, "create_printer") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PLUS, "Add Printer"),
|
|
format!("{} {}", icons::PLUS, "Add Printer"),
|
|
|
"printers_action_add",
|
|
"printers_action_add",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
- format!("{} {}", icons::ARROWS_CLOCKWISE, "Refresh"),
|
|
|
|
|
- "printers_action_refresh",
|
|
|
|
|
- ),
|
|
|
|
|
- ];
|
|
|
|
|
- self.render_actions_grid_with_keys(ui, "printers_actions_grid", &items);
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ items.push((
|
|
|
|
|
+ format!("{} {}", icons::ARROWS_CLOCKWISE, "Refresh"),
|
|
|
|
|
+ "printers_action_refresh",
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ let items_refs: Vec<(String, &str)> = items.iter().map(|(s, k)| (s.clone(), *k)).collect();
|
|
|
|
|
+ self.render_actions_grid_with_keys(ui, "printers_actions_grid", &items_refs);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
@@ -1011,7 +1181,7 @@ impl RibbonUI {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fn show_label_templates_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32) {
|
|
|
|
|
|
|
+ fn show_label_templates_tab(&mut self, ui: &mut egui::Ui, ribbon_height: f32, permissions: Option<&serde_json::Value>) {
|
|
|
// Clear one-shot action triggers from previous frame
|
|
// Clear one-shot action triggers from previous frame
|
|
|
for key in ["labels_action_add", "labels_action_refresh"] {
|
|
for key in ["labels_action_add", "labels_action_refresh"] {
|
|
|
self.checkboxes.insert(key.to_string(), false);
|
|
self.checkboxes.insert(key.to_string(), false);
|
|
@@ -1021,19 +1191,25 @@ impl RibbonUI {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|
|
|
ui.label("Actions");
|
|
ui.label("Actions");
|
|
|
- let items = vec![
|
|
|
|
|
- (
|
|
|
|
|
|
|
+ let mut items = Vec::new();
|
|
|
|
|
+
|
|
|
|
|
+ if Self::check_permission(permissions, "create_label_template") {
|
|
|
|
|
+ items.push((
|
|
|
format!("{} {}", icons::PLUS, "Add Template"),
|
|
format!("{} {}", icons::PLUS, "Add Template"),
|
|
|
"labels_action_add",
|
|
"labels_action_add",
|
|
|
- ),
|
|
|
|
|
- (
|
|
|
|
|
- format!("{} {}", icons::ARROWS_CLOCKWISE, "Refresh"),
|
|
|
|
|
- "labels_action_refresh",
|
|
|
|
|
- ),
|
|
|
|
|
- ];
|
|
|
|
|
- self.render_actions_grid_with_keys(ui, "labels_actions_grid", &items);
|
|
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ items.push((
|
|
|
|
|
+ format!("{} {}", icons::ARROWS_CLOCKWISE, "Refresh"),
|
|
|
|
|
+ "labels_action_refresh",
|
|
|
|
|
+ ));
|
|
|
|
|
+
|
|
|
|
|
+ let items_refs: Vec<(String, &str)> = items.iter().map(|(s, k)| (s.clone(), *k)).collect();
|
|
|
|
|
+ self.render_actions_grid_with_keys(ui, "labels_actions_grid", &items_refs);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
ui.group(|ui| {
|
|
ui.group(|ui| {
|
|
|
ui.set_height(ribbon_height);
|
|
ui.set_height(ribbon_height);
|
|
|
ui.vertical(|ui| {
|
|
ui.vertical(|ui| {
|