View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.client.console.wicket.markup.html.form;
20  
21  import java.io.Serializable;
22  import java.util.Optional;
23  import org.apache.commons.lang3.StringUtils;
24  import org.apache.syncope.client.console.SyncopeConsoleSession;
25  import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
26  import org.apache.syncope.client.console.wicket.markup.html.link.VeilPopupSettings;
27  import org.apache.syncope.client.ui.commons.Constants;
28  import org.apache.wicket.AttributeModifier;
29  import org.apache.wicket.ajax.AjaxRequestTarget;
30  import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
31  import org.apache.wicket.event.Broadcast;
32  import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
33  import org.apache.wicket.markup.html.basic.Label;
34  import org.apache.wicket.markup.html.link.AbstractLink;
35  import org.apache.wicket.markup.html.link.BookmarkablePageLink;
36  import org.apache.wicket.markup.html.panel.Panel;
37  import org.apache.wicket.model.IModel;
38  import org.apache.wicket.model.ResourceModel;
39  
40  /**
41   * This empty class must exist because there not seems to be alternative to provide specialized HTML for edit links.
42   *
43   * @param <T> model object type.
44   */
45  public final class ActionPanel<T extends Serializable> extends Panel {
46  
47      private static final long serialVersionUID = 322966537010107771L;
48  
49      private final Label actionIcon;
50  
51      private final Label actionLabel;
52  
53      private boolean disableIndicator = false;
54  
55      private final Action<T> action;
56  
57      public ActionPanel(final IModel<T> model, final Action<T> action) {
58          this(Constants.ACTION, model, action);
59      }
60  
61      public ActionPanel(final String componentId, final IModel<T> model, final Action<T> action) {
62          super(componentId);
63          setOutputMarkupId(true);
64          this.action = action;
65  
66          T obj = Optional.ofNullable(model).map(IModel::getObject).orElse(null);
67  
68          boolean enabled;
69          AbstractLink actionLink;
70  
71          if (action.getLink() == null || action.getType() == ActionType.NOT_FOUND) {
72              enabled = true;
73              actionLink = new IndicatingAjaxLink<Void>(Constants.ACTION) {
74  
75                  private static final long serialVersionUID = -7978723352517770644L;
76  
77                  @Override
78                  public boolean isEnabled() {
79                      return false;
80                  }
81  
82                  @Override
83                  public void onClick(final AjaxRequestTarget target) {
84                  }
85              };
86          } else if (action.getType() == ActionType.EXTERNAL_EDITOR) {
87              enabled = action.getLink().isEnabled(obj);
88              actionLink = new BookmarkablePageLink<>(
89                      Constants.ACTION, action.getLink().getPageClass(), action.getLink().getPageParameters()).
90                      setPopupSettings(new VeilPopupSettings().setHeight(600).setWidth(800));
91          } else {
92              enabled = action.getLink().isEnabled(obj);
93  
94              actionLink = action.isOnConfirm()
95                      ? new IndicatingOnConfirmAjaxLink<Void>(
96                              Constants.ACTION,
97                              StringUtils.isNotBlank(action.getLink().getConfirmMessage())
98                              ? action.getLink().getConfirmMessage()
99                              : Constants.CONFIRM_DELETE, enabled) {
100 
101                 private static final long serialVersionUID = -7978723352517770644L;
102 
103                 @Override
104                 public void onClick(final AjaxRequestTarget target) {
105                     beforeOnClick(target);
106                     action.getLink().onClick(target, obj);
107                 }
108 
109                 @Override
110                 public String getAjaxIndicatorMarkupId() {
111                     return disableIndicator || !action.getLink().isIndicatorEnabled()
112                             ? StringUtils.EMPTY : Constants.VEIL_INDICATOR_MARKUP_ID;
113                 }
114             }
115                     : new IndicatingAjaxLink<Void>(Constants.ACTION) {
116 
117                 private static final long serialVersionUID = -7978723352517770644L;
118 
119                 @Override
120                 public void onClick(final AjaxRequestTarget target) {
121                     beforeOnClick(target);
122                     action.getLink().onClick(target, obj);
123                 }
124 
125                 @Override
126                 public String getAjaxIndicatorMarkupId() {
127                     return disableIndicator || !action.getLink().isIndicatorEnabled()
128                             ? StringUtils.EMPTY : Constants.VEIL_INDICATOR_MARKUP_ID;
129                 }
130             };
131         }
132 
133         if (SyncopeConsoleSession.get().owns(action.getEntitlements(), action.getRealms())) {
134             MetaDataRoleAuthorizationStrategy.authorizeAll(actionLink, RENDER);
135         } else {
136             MetaDataRoleAuthorizationStrategy.unauthorizeAll(actionLink, RENDER);
137         }
138 
139         actionLink.setVisible(enabled);
140 
141         actionIcon = new Label("actionIcon", "");
142         actionLink.add(actionIcon);
143 
144         String clazz = action.getType().name().toLowerCase() + ".class";
145         actionIcon.add(new AttributeModifier("class", new ResourceModel(clazz, clazz)));
146 
147         String title = action.getType().name().toLowerCase() + ".title";
148         IModel<String> titleModel = new ResourceModel(title, title);
149         actionIcon.add(new AttributeModifier("title", titleModel));
150 
151         String alt = action.getType().name().toLowerCase() + ".alt";
152         actionIcon.add(new AttributeModifier("alt", new ResourceModel(alt, alt)));
153 
154         actionLabel = new Label("label", titleModel);
155         actionLink.add(actionLabel);
156         add(actionLink);
157 
158         // ---------------------------
159         // Action configuration
160         // ---------------------------
161         actionLabel.setVisible(action.isVisibleLabel());
162 
163         Optional.ofNullable(action.getLabel()).ifPresent(actionLabel::setDefaultModel);
164 
165         Optional.ofNullable(action.getTitle()).ifPresent(t -> actionIcon.add(new AttributeModifier("title", t)));
166 
167         Optional.ofNullable(action.getAlt()).ifPresent(a -> actionIcon.add(new AttributeModifier("alt", a)));
168 
169         Optional.ofNullable(action.getIcon()).ifPresent(i -> actionIcon.add(new AttributeModifier("class", i)));
170 
171         this.disableIndicator = !action.hasIndicator();
172         // ---------------------------
173     }
174 
175     protected void beforeOnClick(final AjaxRequestTarget target) {
176         switch (this.action.getType()) {
177             case DELETE:
178             case CREATE:
179             case MEMBERS:
180             case MAPPING:
181             case SET_LATEST_SYNC_TOKEN:
182             case REMOVE_SYNC_TOKEN:
183             case EDIT_APPROVAL:
184             case CLAIM:
185                 send(this, Broadcast.BUBBLE, new ActionLinksTogglePanel.ActionLinkToggleCloseEventPayload(target));
186                 break;
187             default:
188                 break;
189         }
190     }
191 }