tablo_core/table/
wiring.rs1use std::{ops::Deref, sync::Arc};
4
5use topcoat::context::Cx;
6
7use super::{
8 RowActions, RowPolicy, Table, TableAction,
9 state::{TableSignals, TableState},
10};
11
12pub(crate) struct Wiring<M> {
18 row_policy: Option<RowPolicy<M>>,
19 delete_prefix: Option<String>,
20 edit_prefix: Option<String>,
21 view_prefix: Option<String>,
22 bulk_delete: bool,
23 custom_actions: Vec<TableAction<M>>,
25 actions_prefix: Option<String>,
26 return_to: Option<String>,
28 prefix: Option<String>,
30}
31
32impl<M> Default for Wiring<M> {
33 fn default() -> Self {
34 Self {
35 row_policy: None,
36 delete_prefix: None,
37 edit_prefix: None,
38 view_prefix: None,
39 bulk_delete: false,
40 custom_actions: Vec::new(),
41 actions_prefix: None,
42 return_to: None,
43 prefix: None,
44 }
45 }
46}
47
48pub struct WiredTable<M> {
54 table: Arc<Table<M>>,
55 pub(super) wiring: Wiring<M>,
56}
57
58impl<M> Deref for WiredTable<M> {
59 type Target = Table<M>;
60
61 fn deref(&self) -> &Table<M> {
62 &self.table
63 }
64}
65
66impl<M> std::fmt::Debug for WiredTable<M> {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 let wiring = &self.wiring;
69 f.debug_struct("WiredTable")
70 .field("table", &self.table)
71 .field("row_policy", &wiring.row_policy.is_some())
72 .field("delete_prefix", &wiring.delete_prefix)
73 .field("edit_prefix", &wiring.edit_prefix)
74 .field("view_prefix", &wiring.view_prefix)
75 .field("bulk_delete", &wiring.bulk_delete)
76 .field(
77 "custom_actions",
78 &wiring
79 .custom_actions
80 .iter()
81 .map(|a| a.name)
82 .collect::<Vec<_>>(),
83 )
84 .field("return_to", &wiring.return_to)
85 .field("prefix", &wiring.prefix)
86 .finish()
87 }
88}
89
90impl<M> WiredTable<M> {
91 pub(crate) fn new(table: Arc<Table<M>>) -> Self {
93 Self {
94 table,
95 wiring: Wiring::default(),
96 }
97 }
98
99 pub(crate) fn row_actions(
101 mut self,
102 policy: impl Fn(&M) -> RowActions + Send + Sync + 'static,
103 ) -> Self {
104 self.wiring.row_policy = Some(Arc::new(policy));
105 self
106 }
107
108 pub(crate) fn with_delete(mut self, prefix: String) -> Self {
110 if self.addressable {
111 self.wiring.delete_prefix = Some(prefix);
112 }
113 self
114 }
115
116 pub(crate) fn with_edit(mut self, prefix: String) -> Self {
118 if self.addressable {
119 self.wiring.edit_prefix = Some(prefix);
120 }
121 self
122 }
123
124 pub(crate) fn with_view(mut self, prefix: String) -> Self {
126 if self.addressable {
127 self.wiring.view_prefix = Some(prefix);
128 }
129 self
130 }
131
132 pub(crate) fn with_bulk_delete(mut self, enabled: bool) -> Self {
134 self.wiring.bulk_delete = enabled;
135 self
136 }
137
138 pub(crate) fn with_custom_actions(
140 mut self,
141 prefix: String,
142 actions: Vec<TableAction<M>>,
143 ) -> Self {
144 if self.addressable {
145 self.wiring.actions_prefix = Some(prefix);
146 self.wiring.custom_actions = actions;
147 }
148 self
149 }
150
151 pub(crate) fn returning_to(mut self, url: String) -> Self {
153 self.wiring.return_to = Some(url);
154 self
155 }
156
157 #[must_use]
160 pub fn prefixed(mut self, prefix: impl Into<String>) -> Self {
161 self.wiring.prefix = Some(prefix.into());
162 self
163 }
164
165 pub(crate) fn browser_state(&self, cx: &Cx) -> (TableSignals, TableState) {
168 let prefix = self.wiring.prefix.as_deref();
169 let signals = TableSignals::new(cx, prefix);
170 let state = self.normalize_state(&signals.state(prefix));
171 (signals, state)
172 }
173
174 pub(crate) fn actions_for(&self, record: &M) -> RowActions {
176 self.wiring
177 .row_policy
178 .as_ref()
179 .map_or(RowActions::ALL, |policy| policy(record))
180 }
181
182 pub(super) fn return_to(&self) -> Option<&str> {
183 self.wiring.return_to.as_deref()
184 }
185
186 pub(super) fn delete_prefix(&self) -> Option<&str> {
187 self.wiring.delete_prefix.as_deref()
188 }
189
190 pub(super) fn edit_prefix(&self) -> Option<&str> {
191 self.wiring.edit_prefix.as_deref()
192 }
193
194 pub(super) fn view_prefix(&self) -> Option<&str> {
195 self.wiring.view_prefix.as_deref()
196 }
197
198 pub(super) fn actions_prefix(&self) -> Option<&str> {
199 self.wiring.actions_prefix.as_deref()
200 }
201
202 pub(super) fn row_custom_actions(&self) -> impl Iterator<Item = &TableAction<M>> {
203 self.wiring
204 .custom_actions
205 .iter()
206 .filter(|a| a.row && self.wiring.actions_prefix.is_some())
207 }
208
209 pub(super) fn bulk_custom_actions(&self) -> impl Iterator<Item = &TableAction<M>> {
210 self.wiring
211 .custom_actions
212 .iter()
213 .filter(|a| a.bulk && self.wiring.actions_prefix.is_some())
214 }
215
216 pub(super) fn bulk_delete_enabled(&self) -> bool {
217 self.wiring.bulk_delete && self.wiring.delete_prefix.is_some()
218 }
219}
220
221#[cfg(test)]
222impl<M> Table<M> {
223 pub(crate) fn wired(self) -> WiredTable<M> {
225 WiredTable::new(Arc::new(self))
226 }
227}