BrightSide Workbench Full Report + Source Code
FunnelItemsVM.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2022 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 package org.turro.web.funnel.model;
20 
21 import java.io.StringWriter;
22 import java.io.Writer;
23 import java.util.Collections;
24 import java.util.List;
25 import org.turro.elephant.db.ElephantPU;
26 import org.turro.elephant.entities.web.WebGoal;
27 import org.turro.elephant.entities.web.WebItem;
28 import org.turro.elephant.util.Messages;
29 import org.turro.elephant.util.Toasts;
30 import org.turro.elephant.web.actions.WebActionType;
31 import org.turro.elephant.entities.web.WebItemType;
32 import org.turro.i18n.I_;
33 import org.turro.jpa.Dao;
34 import org.turro.sql.SqlClause;
35 import org.turro.string.Strings;
36 import org.turro.util.Cached;
37 import org.turro.web.funnel.graph.FunnelGraph;
38 import org.turro.web.funnel.graph.FunnelGraphDOT;
39 import org.turro.zkoss.dialog.DialogField;
40 import org.turro.zkoss.dialog.Dialogs;
41 import org.zkoss.bind.BindUtils;
42 import org.zkoss.bind.annotation.BindingParam;
43 import org.zkoss.bind.annotation.NotifyChange;
44 import org.zkoss.zk.ui.Executions;
45 import org.zkoss.zul.Textbox;
46 
51 public class FunnelItemsVM {
52 
53  public WebItem getSelected() {
54  return selected;
55  }
56 
57  public void setSelected(WebItem selected) {
58  this.selected = selected;
59  this.behaveAs = FunnelGraph.behaveAs(selected);
60  BindUtils.postNotifyChange(null, null, FunnelItemsVM.this,
61  "selected", "behaveString", "showForm", "nextsModel");
62  }
63 
64  public String getBehaveString() {
65  if(selected == null || behaveAs == null) return "wrong";
66  if(selected.getType().equals(behaveAs)) return "equal";
67  if(WebItemType.CHAIN.equals(behaveAs)) return "wrong";
68  return behaveAs.toString();
69  }
70 
71  public String getGraphDOT() {
72  Writer writer = new StringWriter();
73  FunnelGraphDOT.DOT(writer);
74  return writer.toString();
75  }
76 
77  public boolean isShowForm() {
78  return selected != null;
79  }
80 
81  public void addItem() {
82  Dialogs.title(I_.get("Add"))
83  .width("400px")
84  .height("250px")
85  .addField(DialogField.field("WebTag"))
86  .addField(DialogField.field("Type").onEditor(() -> {
87  WebItemTypeListbox wit = new WebItemTypeListbox();
88  wit.setMold("select");
89  wit.setObjectValue(WebItemType.TARGET);
90  return wit;
91  }))
92  .onOk((dialogs) -> {
93  String webTag = dialogs.<Textbox>getEditor("WebTag").getValue();
94  if(notInModel(webTag)) {
95  WebItem wi = new WebItem();
96  wi.setWebTag(webTag);
97  wi.setType(dialogs.<WebItemTypeListbox>getEditor("Type").getObjectValue());
98  if(wi.isValid()) {
99  model.add(wi);
100  selected = wi;
101  BindUtils.postNotifyChange(null, null, FunnelItemsVM.this,
102  "model", "selected", "showForm");
103  } else {
104  Toasts.message("WebTags should not include spaces or punctuation characters.").show();
105  }
106  } else {
107  Toasts.message("WebTag already in the model.").show();
108  }
109  })
110  .emptyCancel()
111  .show();
112  }
113 
114  @NotifyChange({"model", "selected", "showForm"})
115  public void save() {
116  model.stream().filter(wi -> wi.isEmpty() && !wi.isNew())
117  .forEach(wi -> dao.get().deleteEntity(wi));
118  model.removeIf(wi -> wi.isEmpty());
119  model.forEach(wi -> wi.compose());
120  dao.get().saveEntities(model);
121  Executions.getCurrent().sendRedirect(null);
122  }
123 
124  @NotifyChange({"selected", "nextsModel"})
125  public void addNext(@BindingParam("next") WebItem item) {
126  selected.getNexts().add(item);
127  }
128 
129  @NotifyChange({"selected", "goalsModel"})
130  public void addGoal(@BindingParam("goal") WebGoal goal) {
131  selected.getGoals().add(goal);
132  }
133 
134  public void addExt() {
135  Dialogs.title(I_.get("Add external"))
136  .width("400px")
137  .height("300px")
138  .addField(DialogField.field("Type")
139  .help("https://www.turro.org/docs/elephant/components/webactions")
140  .onEditor(() -> {
141  WebActionTypeListbox wat = new WebActionTypeListbox();
142  wat.setMold("select");
143  wat.setObjectValue(WebActionType.NAVIGATE);
144  return wat;
145  }))
146  .addField(DialogField.field("Value"))
147  .addField(DialogField.field("Icon"))
148  .onOk((dialogs) -> {
149  WebActionType type = dialogs.<WebActionTypeListbox>getEditor("Type").getObjectValue();
150  String value = dialogs.<Textbox>getEditor("Value").getValue();
151  String image = dialogs.<Textbox>getEditor("Icon").getValue();
152  if(type != null && !Strings.isBlank(value)) {
153  selected.getExternals().add(type.getProtocol() + ":" + value +
154  (Strings.isBlank(image) ? "" : "{" + image + "}"));
155  BindUtils.postNotifyChange(null, null, FunnelItemsVM.this,
156  "selected");
157  }
158  })
159  .emptyCancel()
160  .show();
161  }
162 
163  public void delete() {
164  Messages.confirmDeletion().add(selected.getItemLabel()).show(() -> {
165  dao.get().deleteObject(selected);
166  Executions.getCurrent().sendRedirect(null);
167  });
168  }
169 
170  public void deleteNext(@BindingParam("next") WebItem item) {
171  Messages.confirmDeletion().add(item.getItemLabel()).show(() -> {
172  selected.getNexts().remove(item);
173  BindUtils.postNotifyChange(null, null, FunnelItemsVM.this,
174  "model", "selected");
175  });
176  }
177 
178  public void deleteGoal(@BindingParam("goal") WebGoal goal) {
179  Messages.confirmDeletion().add(goal.getItemLabel()).show(() -> {
180  selected.getGoals().remove(goal);
181  BindUtils.postNotifyChange(null, null, FunnelItemsVM.this,
182  "model", "selected");
183  });
184  }
185 
186  public void deleteExt(@BindingParam("ext") String item) {
187  Messages.confirmDeletion().add(item).show(() -> {
188  selected.getExternals().remove(item);
189  BindUtils.postNotifyChange(null, null, FunnelItemsVM.this,
190  "selected");
191  });
192  }
193 
194  /* Utils */
195 
196  private boolean notInModel(String webTag) {
197  return !getModel().stream().anyMatch(wi -> wi.getWebTag().equals(webTag));
198  }
199 
200  private List<WebItemType> getPossibleNextTypes() {
201  if(behaveAs == null) return Collections.EMPTY_LIST;
202  return switch(behaveAs) {
203  case TARGET -> List.of(WebItemType.SOLUTION, WebItemType.CHAIN);
204  case SOLUTION -> List.of(WebItemType.SERVICE, WebItemType.CHAIN);
205  case SERVICE -> List.of(WebItemType.CHAIN);
206  default -> Collections.EMPTY_LIST;
207  };
208  }
209 
210  /* Models */
211 
212  private WebItem selected;
213  private WebItemType behaveAs;
214 
215  private List<WebItem> model;
216 
217  public List<WebItem> getModel() {
218  if(model == null) {
219  model = SqlClause.select("wi").from("WebItem wi")
220  .orderBy("type, ordering, webTag")
221  .dao(dao.get())
222  .resultList(WebItem.class);
223  }
224  return model;
225  }
226 
227  public List<WebItem> getNextsModel() {
228  if(selected == null) return Collections.EMPTY_LIST;
229  return SqlClause.select("wi").from("WebItem wi")
230  .where().in("type", getPossibleNextTypes())
231  .and().notEqual("webTag", selected.getWebTag())
232  .and().notIn("webTag", selected.getNexts().stream().map(wi -> wi.getWebTag()).toList())
233  .dao(dao.get())
234  .resultList(WebItem.class);
235  }
236 
237  public List<WebGoal> getGoalsModel() {
238  if(selected == null) return Collections.EMPTY_LIST;
239  return SqlClause.select("wg").from("WebGoal wg")
240  .where().notIn("goalAction", selected.getGoals().stream().map(wi -> wi.getGoalAction()).toList())
241  .dao(dao.get())
242  .resultList(WebGoal.class);
243  }
244 
245  /* Dao */
246 
247  private final Cached<Dao> dao = Cached.instance(() -> new ElephantPU());
248 
249 }
void setType(WebItemType type)
Definition: WebItem.java:99
static Messages confirmDeletion()
Definition: Messages.java:87
Messages add(String word)
Definition: Messages.java:50
static Toasts message(String message)
Definition: Toasts.java:114
static String get(String msg)
Definition: I_.java:41
static WebItemType behaveAs(WebItem item)
void deleteNext(@BindingParam("next") WebItem item)
void addGoal(@BindingParam("goal") WebGoal goal)
void deleteExt(@BindingParam("ext") String item)
void deleteGoal(@BindingParam("goal") WebGoal goal)
void addNext(@BindingParam("next") WebItem item)
static DialogField field(String label)
Dialogs width(String width)
Definition: Dialogs.java:70
Dialogs height(String height)
Definition: Dialogs.java:75
Dialogs onOk(Consumer< Dialogs > onOk)
Definition: Dialogs.java:85
static Dialogs title(String title)
Definition: Dialogs.java:161
Dialogs addField(DialogField field)
Definition: Dialogs.java:110